﻿#include "databasemanager.h"
#include <QSqlQuery>
#include <QSqlError>
#include <QVariant>
#include <QDebug>
#include <QFile>

DatabaseManager::DatabaseManager(const QString &dbPath)
{
    m_db = QSqlDatabase::addDatabase("QSQLITE");
    m_db.setDatabaseName(dbPath);

    if (!m_db.open()) {
        qCritical() << "Database connection failed:" << m_db.lastError().text();
    } else {
        qDebug() << "Database connected successfully.";
        initDatabase();
    }
}

DatabaseManager::~DatabaseManager()
{
    if (m_db.isOpen()) {
        m_db.close();
    }
}

bool DatabaseManager::isOpen() const
{
    return m_db.isOpen();
}

void DatabaseManager::initTestTemplateDatabase()
{
    // 主表：TestTemplates（包含基础字段 + UI 绘图配置）
    // 说明：calibration_table_id 关联 CalibrationTables_Meta(id)
    executeQuery(
        "CREATE TABLE IF NOT EXISTS TestTemplates ("
        "  id INTEGER PRIMARY KEY AUTOINCREMENT,"
        "  name TEXT UNIQUE NOT NULL,"
        "  flow_kind INTEGER,"
        "  level_mode INTEGER,"
        "  power_measurement INTEGER,"
        "  immunity_level_unit TEXT,"
        "  impedance REAL,"
        "  calibration_table_id INTEGER NULL REFERENCES CalibrationTables_Meta(id) ON DELETE SET NULL,"
        "  offset_check INTEGER,"
        "  offset REAL,"
        //- UI 绘图配置（全部可为空）
        "  check_generator_output INTEGER,"
        "  generator_output_ymax REAL,"
        "  generator_output_ymin REAL,"
        "  generator_output_x_axis_scale INTEGER,"
        "  generator_output_y_axis_scale INTEGER,"
        "  check_amplifier_fp INTEGER,"
        "  amplifier_fp_ymax REAL,"
        "  amplifier_fp_ymin REAL,"
        "  amplifier_fp_x_axis_scale INTEGER,"
        "  amplifier_fp_y_axis_scale INTEGER,"
        "  check_amplifier_rp INTEGER,"
        "  amplifier_rp_ymax REAL,"
        "  amplifier_rp_ymin REAL,"
        "  amplifier_rp_x_axis_scale INTEGER,"
        "  amplifier_rp_y_axis_scale INTEGER,"
        "  check_vswr INTEGER,"
        "  vswr_ymax REAL,"
        "  vswr_ymin REAL,"
        "  vswr_x_axis_scale INTEGER,"
        "  vswr_y_axis_scale INTEGER,"
        "  check_immunity_level INTEGER,"
        "  immunity_level_ymax REAL,"
        "  immunity_level_ymin REAL,"
        "  immunity_level_x_axis_scale INTEGER,"
        "  immunity_level_y_axis_scale INTEGER"
        ");",
        "Create TestTemplates");

    // 子表：TestSubBands（子区间，带 ordinal 保序）
    // 说明：
    // - hardware_template_id -> HardwareTemplates(id)
    // - freq_table_id -> FreqTables_Meta(id)
    // - immunity_level_table_id -> LimitLines_Meta(id)
    executeQuery(
        "CREATE TABLE IF NOT EXISTS TestSubBands ("
        "  id INTEGER PRIMARY KEY AUTOINCREMENT,"
        "  test_template_id INTEGER NOT NULL REFERENCES TestTemplates(id) ON DELETE CASCADE,"
        "  hardware_template_id INTEGER NULL REFERENCES HardwareTemplates(id) ON DELETE SET NULL,"
        "  start_freq_hz REAL NOT NULL,"
        "  stop_freq_hz REAL NOT NULL,"
        "  step_size REAL,"
        "  step_mode REAL,"
        "  dwell_time_ms REAL,"
        "  freq_plan INTEGER NOT NULL,"
        "  freq_table_id INTEGER NULL REFERENCES FreqTables_Meta(id) ON DELETE SET NULL,"
        "  immunity_level_type INTEGER NOT NULL,"
        "  immunity_level_table_id INTEGER NULL REFERENCES LimitLines_Meta(id) ON DELETE SET NULL,"
        "  immunity_level_value REAL,"
        "  upper_tolerance_db REAL,"
        "  lower_tolerance_db REAL,"
        "  generator_modulation INTEGER NOT NULL,"
        "  generator_plum_period REAL,"
        "  generator_plum_width REAL,"
        "  ordinal INTEGER NOT NULL"
        ");",
        "Create TestSubBands");
}

void DatabaseManager::initDatabase()
{
    initHardwareDatabase();
    initTestTemplateDatabase();
}

void DatabaseManager::initTableDatabase()
{
}

void DatabaseManager::initHardwareDatabase()
{
    qDebug() << "Initializing/Verifying database schema...";

    // 准备工作：开启外键约束支持
    if (!executeQuery("PRAGMA foreign_keys = ON;", "Enable Foreign Keys")) {
        qCritical() << "Could not enable foreign key support. Data integrity is at risk.";
        return;
    }

    // ===================================================================
    // 块 1: 可复用的“列表/表格”数据定义表
    // 每一个都遵循 "元数据(Meta)" + "数据点(Points)" 的设计模式
    // ===================================================================

    // -- 衰减表 (对应 AttTableList) --
    executeQuery("CREATE TABLE IF NOT EXISTS AttTables_Meta ("
                 "id INTEGER PRIMARY KEY AUTOINCREMENT,"
                 "name TEXT UNIQUE NOT NULL,"
                 "x_axis_scale INTEGER, y_axis_scale INTEGER);",
                 "Create AttTables Meta");

    executeQuery("CREATE TABLE IF NOT EXISTS AttTables_Points ("
                 "id INTEGER PRIMARY KEY AUTOINCREMENT,"
                 "table_id INTEGER NOT NULL,"
                 "freq REAL, att REAL,"
                 "FOREIGN KEY(table_id) REFERENCES AttTables_Meta(id) ON DELETE CASCADE);",
                 "Create AttTables Points");

    // -- 换能器/因子表 (对应 TransducerTableList) --
    executeQuery("CREATE TABLE IF NOT EXISTS TransducerTables_Meta ("
                 "id INTEGER PRIMARY KEY AUTOINCREMENT,"
                 "name TEXT UNIQUE NOT NULL,"
                 "x_axis_scale INTEGER, y_axis_scale INTEGER,"
                 "x_unit TEXT, y_unit TEXT, source_unit TEXT, target_unit TEXT);",
                 "Create TransducerTables Meta");

    executeQuery("CREATE TABLE IF NOT EXISTS TransducerTables_Points ("
                 "id INTEGER PRIMARY KEY AUTOINCREMENT,"
                 "table_id INTEGER NOT NULL,"
                 "freq REAL, factors REAL,"
                 "FOREIGN KEY(table_id) REFERENCES TransducerTables_Meta(id) ON DELETE CASCADE);",
                 "Create TransducerTables Points");

    // -- 极值线表 (对应 LimitLineList) --
    executeQuery("CREATE TABLE IF NOT EXISTS LimitLines_Meta ("
                 "id INTEGER PRIMARY KEY AUTOINCREMENT,"
                 "name TEXT UNIQUE NOT NULL,"
                 "x_unit TEXT, y_unit TEXT,"
                 "x_axis_scale INTEGER, y_axis_scale INTEGER);",
                 "Create LimitLines Meta");

    executeQuery("CREATE TABLE IF NOT EXISTS LimitLines_Points ("
                 "id INTEGER PRIMARY KEY AUTOINCREMENT,"
                 "table_id INTEGER NOT NULL,"
                 "freq REAL, limit_val REAL," // limit_val to avoid SQL keyword 'limit'
                 "FOREIGN KEY(table_id) REFERENCES LimitLines_Meta(id) ON DELETE CASCADE);",
                 "Create LimitLines Points");

    executeQuery("CREATE TABLE IF NOT EXISTS FreqTables_Meta (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE NOT NULL);",
                 "Create FreqTables Meta");
    executeQuery("CREATE TABLE IF NOT EXISTS FreqTables_Points ("
                 "id INTEGER PRIMARY KEY AUTOINCREMENT, "
                 "table_id INTEGER NOT NULL, "
                 "freq REAL, "
                 "FOREIGN KEY(table_id) REFERENCES FreqTables_Meta(id) ON DELETE CASCADE);",
                 "Create FreqTables Points");

    executeQuery("CREATE TABLE IF NOT EXISTS CalibrationTables_Meta ("
                 "id INTEGER PRIMARY KEY AUTOINCREMENT,"
                 "name TEXT UNIQUE NOT NULL,"
                 "created_at TEXT DEFAULT CURRENT_TIMESTAMP,"
                 "updated_at TEXT,"
                 "notes TEXT);",
                 "Create CalibrationTables Meta");
    executeQuery("CREATE TABLE IF NOT EXISTS CalibrationTables_Points("
                 "id INTEGER PRIMARY KEY AUTOINCREMENT,"
                 "table_id INTEGER NOT NULL,"
                 "freq REAL, amplitude REAL, fwd_power REAL, rev_power REAL,"
                 "immunity_level_unit TEXT, immunity_level REAL, limit_immunity_level REAL,"
                 "swr REAL, loss REAL, close_loop INTEGER, info TEXT,"
                 "FOREIGN KEY(table_id) REFERENCES CalibrationTables_Meta(id) ON DELETE CASCADE);",
                 "Create CalibrationTables Points");

    // ===================================================================
    // 块 2: 模板与私有设备定义表
    // ===================================================================

    // -- 硬件模板主表 (现在非常简洁) --
    executeQuery("CREATE TABLE IF NOT EXISTS HardwareTemplates ("
                 "id INTEGER PRIMARY KEY AUTOINCREMENT,"
                 "name TEXT UNIQUE NOT NULL,"
                 "template_frequency_min REAL NULL,"
                 "template_frequency_max REAL NULL,"
                 "template_type INTEGER NOT NULL" // HardwareTemplateType
                 ");",
                 "Create HardwareTemplates Table");

    // -- 模板私有设备表 (TemplateDevices) --
    // 这是一个包含所有设备属性的“大宽表”
    // 每一行都代表一个属于特定硬件模板的、扮演特定角色的设备实例
    executeQuery("CREATE TABLE IF NOT EXISTS TemplateDevices ("
                 "id INTEGER PRIMARY KEY AUTOINCREMENT,"
                 // 核心关联与角色定义
                 "hardware_template_id INTEGER NOT NULL REFERENCES HardwareTemplates(id) ON DELETE CASCADE,"
                 "device_role INTEGER NOT NULL," // 对应 DeviceRole 枚举

                 // 通用属性
                 "device_type INTEGER NOT NULL," // 对应 DeviceType 枚举
                 "model TEXT NULL,"
                 "library_path TEXT NULL,"
                 "interface_type INTEGER NULL,"
                 "interface_addr TEXT NOT NULL,"

                 // GeneratorConfig 特有属性 (可为 NULL)
                 "generator_level_min REAL NULL,"
                 "generator_level_max REAL NULL,"
                 "generator_mod_frequency REAL NULL,"
                 "generator_mod_depth REAL NULL,"
                 "generator_mod_deviation REAL NULL,"
                 "generator_mod_pulse_width REAL NULL,"

                 // AmplifierConfig 特有属性 (可为 NULL)
                 "amplifier_input_level_max REAL NULL,"
                 "amplifier_coupler_type INTEGER NULL,"
                 "amplifier_coupler_value REAL NULL,"
                 "amplifier_fwd_table_id INTEGER NULL REFERENCES AttTables_Meta(id) ON DELETE SET NULL,"
                 "amplifier_rev_table_id INTEGER NULL REFERENCES AttTables_Meta(id) ON DELETE SET NULL,"

                 // PowerMeterConfig 特有属性 (可为 NULL)
                 "power_meter_channel TEXT NULL,"

                 // AntennaConfig 特有属性 (可为 NULL)
                 "antenna_h_factors_table_id INTEGER NULL REFERENCES TransducerTables_Meta(id) ON DELETE SET NULL,"
                 "antenna_v_factors_table_id INTEGER NULL REFERENCES TransducerTables_Meta(id) ON DELETE SET NULL,"

                 // FieldProbesConfig 特有属性 (可为 NULL)
                 "field_probe_correction_xyz_table_id INTEGER NULL REFERENCES AttTables_Meta(id) ON DELETE SET NULL,"

                 // CurrentInjectionProbeConfig 特有属性 (可为 NULL)
                 "ci_probe_transducer_table_id INTEGER NULL REFERENCES TransducerTables_Meta(id) ON DELETE SET NULL,"

                 // ConnectorConfig 特有属性 (可为 NULL)
                 "connector_value_type INTEGER NULL,"
                 "connector_att_value REAL NULL,"
                 "connector_switch_path INTEGER NULL,"
                 "connector_switch_channel INTEGER NULL,"
                 "connector_att_table_id INTEGER NULL REFERENCES AttTables_Meta(id) ON DELETE SET NULL,"

                 // SpectrumAnalyzerConfig 没有特有属性，所以没有它的字段

                 // 约束，确保每个模板的每个角色只有一个设备
                 "UNIQUE(hardware_template_id, device_role)"
                 ");",
                 "Create TemplateDevices Table");

    qDebug() << "Database schema initialization complete.";
}

// executeQuery，只支持命名绑定
bool DatabaseManager::executeQuery(QSqlQuery &query, const QString &sql, const QVariantMap &bindings, const QString &context)
{
    if (!query.prepare(sql)) {
        qWarning() << "Query prepare failed:" << (context.isEmpty() ? "" : context) << query.lastError().text();
        qWarning() << "Failing SQL:" << sql;
        return false;
    }

    // 遍历QVariantMap来绑定值
    for (auto it = bindings.constBegin(); it != bindings.constEnd(); ++it) {
        query.bindValue(it.key(), it.value());
    }

    if (!query.exec()) {
        qWarning() << "Query exec failed:" << (context.isEmpty() ? "" : context) << query.lastError().text();
        qWarning() << "Failing query:" << query.lastQuery();
        qWarning() << "Bound values:" << query.boundValues(); // Qt 5.12下用这个
        return false;
    }
    return true;
}

bool DatabaseManager::executeQuery(const QString &sql, const QString &context)
{
    QSqlQuery query(m_db);
    return executeQuery(query, sql, {}, context);
}

/**
 * @brief 从数据库加载所有硬件模板的概览信息 (ID和名称)。
 * @return 返回一个包含所有硬件模板概览的QList。如果查询失败或没有模板，则返回一个空列表。
 */
QList<OverviewItem> DatabaseManager::loadHardwareTemplateOverviews()
{
    //  创建一个空的列表，用于存储结果
    QList<OverviewItem> overviews;

    // 准备SQL查询语句
    // 查询HardwareTemplates表中的id和name字段，并按名称排序以获得一致的显示顺序
    QString sql = "SELECT id, name FROM HardwareTemplates ORDER BY name ASC";

    // 创建一个专门用于本次查询的QSqlQuery对象
    QSqlQuery query(m_db);

    //  调用executeQuery辅助函数执行查询，负责prepare和exec
    if (executeQuery(query, sql, {}, "Load Hardware Template Overviews")) {
        //  如果查询成功，遍历结果集
        qDebug() << "Successfully executed query for hardware template overviews. Processing results...";

        while (query.next()) {
            //  从每一行记录中提取数据，并构建OverviewItem对象
            OverviewItem item;
            item.id = query.value("id").toInt();
            item.name = query.value("name").toString();

            // 将构建好的对象添加到结果列表中
            overviews.append(item);
        }

        qDebug() << "Found" << overviews.size() << "hardware templates.";

    } else {
        qDebug() << "Query for hardware template overviews failed. Returning empty list.";
    }
    return overviews;
}

/**
 * @brief 从数据库加载所有类型的“参数表”的概览信息 (ID, Name, Type)。
 *        此函数不加载“结果日志”类型的表。
 *        使用UNION ALL来高效地合并来自多个元数据表的结果。
 * @return 返回一个包含所有参数表概览的QList。如果查询失败或没有数据，则返回一个空列表。
 */
QList<OverviewItem> DatabaseManager::loadParameterTableOverviews()
{
    QList<OverviewItem> overviews;

    // 构建 UNION ALL 查询语句
    // 为每个元数据表创建一个SELECT子句，并手动添加一个表示其类型的字符串字面量。
    // 最后按类型和名称排序，以便在UI中整齐地显示。
    QString sql =
        "SELECT id, name, 'AttTables' as type FROM AttTables_Meta "
        "UNION ALL "
        "SELECT id, name, 'TransducerTables' as type FROM TransducerTables_Meta "
        "UNION ALL "
        "SELECT id, name, 'LimitLines' as type FROM LimitLines_Meta "
        "UNION ALL "
        "SELECT id, name, 'FreqTables' as type FROM FreqTables_Meta "
        "UNION ALL "
        "SELECT id, name, 'CalibrationTables' as type FROM CalibrationTables_Meta "
        // 注意：在这里 bewusst (有意地) 省略了 Calibrations_Meta 表
        "ORDER BY type, name ASC";

    // 创建并执行查询
    QSqlQuery query(m_db);

    if (!query.prepare(sql)) {
        qWarning() << "Query prepare failed: Load Parameter Table Overviews" << query.lastError().text();
        return overviews; // 返回空列表
    }

    if (!query.exec()) {
        qWarning() << "Query exec failed: Load Parameter Table Overviews" << query.lastError().text();
        qWarning() << "Failing query:" << query.lastQuery();
        return overviews; // 返回空列表
    }

    //  遍历合并后的结果集，并填充列表
    qDebug() << "Successfully executed query for parameter table overviews. Processing results...";

    while (query.next()) {
        OverviewItem item;
        item.id = query.value("id").toInt();
        item.name = query.value("name").toString();
        QString tmp = query.value("type").toString();
        if (tmp == "AttTables")
            item.type = ParamTableKind::Attenuation;
        else if (tmp == "TransducerTables")
            item.type = ParamTableKind::Transducer;
        else if (tmp == "LimitLines")
            item.type = ParamTableKind::LimitLine;
        else if (tmp == "FreqTables")
            item.type = ParamTableKind::Frequency;
        else if (tmp == "CalibrationTables")
            item.type = ParamTableKind::Cal;
        else
            item.type = ParamTableKind::Default;

        overviews.append(item);
    }

    qDebug() << "Found" << overviews.size() << "parameter tables of all types.";

    //  返回填充好的结果列表
    return overviews;
}

QList<OverviewItem> DatabaseManager::loadTestTemplateOverviews()
{
    QList<OverviewItem> out;
    QSqlQuery q(m_db);
    const QString sql = "SELECT id, name FROM TestTemplates ORDER BY name ASC";
    if (executeQuery(q, sql, {}, "Load TestTemplates Overview")) {
        while (q.next()) {
            OverviewItem it;
            it.id = q.value(0).toInt();
            it.name = q.value(1).toString();
            //            it.type = "TestTemplates";
            out.push_back(it);
        }
    }
    return out;
}

TestTemplatePtr DatabaseManager::loadFullTestTemplate(int id)
{
    if (id <= 0)
        return nullptr;

    auto out = QSharedPointer<TestTemplate>::create();
    // 主表
    {
        QSqlQuery q(m_db);
        const QString sql =
            "SELECT name, flow_kind, level_mode, power_measurement, immunity_level_unit, impedance, "
            "calibration_table_id, offset_check, offset, "
            " check_generator_output, generator_output_ymax, generator_output_ymin, "
            " generator_output_x_axis_scale, generator_output_y_axis_scale, "
            " check_amplifier_fp, amplifier_fp_ymax, amplifier_fp_ymin, "
            " amplifier_fp_x_axis_scale, amplifier_fp_y_axis_scale, "
            " check_amplifier_rp, amplifier_rp_ymax, amplifier_rp_ymin, "
            " amplifier_rp_x_axis_scale, amplifier_rp_y_axis_scale, "
            " check_vswr, vswr_ymax, vswr_ymin, vswr_x_axis_scale, vswr_y_axis_scale, "
            " check_immunity_level, immunity_level_ymax, immunity_level_ymin, "
            " immunity_level_x_axis_scale, immunity_level_y_axis_scale "
            "FROM TestTemplates WHERE id=:id";
        QVariantMap b;
        b[":id"] = id;
        if (!executeQuery(q, sql, b, "Load TestTemplate main") || !q.next()) {
            qWarning() << "loadFullTestTemplate: main not found id=" << id;
            return nullptr;
        }

        out->id = id;
        int c = 0;
        out->name = q.value(c++).toString();
        out->flowKind = static_cast<HardwareTemplateType>(q.value(c++).toInt());
        out->levelMode = static_cast<LevelModeType>(q.value(c++).toInt());
        out->powerMeasurement = static_cast<PowerMeasurementType>(q.value(c++).toInt());
        out->immunityLevelUnit = q.value(c++).toString();
        out->impedance = q.value(c++).toDouble();
        out->calibrationDataID = q.value(c++).toInt();
        out->offsetCheck = q.value(c++).toInt();
        out->offset = q.value(c++).toDouble();

        out->CheckGeneratorOutput = q.value(c++).toInt();
        out->GeneratorOutputYmax = q.value(c++).toDouble();
        out->GeneratorOutputYmin = q.value(c++).toDouble();
        out->GeneratorOutputXAxisScale = static_cast<AxisScale>(q.value(c++).toInt());
        out->GeneratorOutputYAxisScale = static_cast<AxisScale>(q.value(c++).toInt());

        out->CheckAmplifierFP = q.value(c++).toInt();
        out->AmplifierFPYmax = q.value(c++).toDouble();
        out->AmplifierFPYmin = q.value(c++).toDouble();
        out->AmplifierFPXAxisScale = static_cast<AxisScale>(q.value(c++).toInt());
        out->AmplifierFPYAxisScale = static_cast<AxisScale>(q.value(c++).toInt());

        out->CheckAmplifierRP = q.value(c++).toInt();
        out->AmplifierRPYmax = q.value(c++).toDouble();
        out->AmplifierRPYmin = q.value(c++).toDouble();
        out->AmplifierRPXAxisScale = static_cast<AxisScale>(q.value(c++).toInt());
        out->AmplifierRPYAxisScale = static_cast<AxisScale>(q.value(c++).toInt());

        out->CheckVSWR = q.value(c++).toInt();
        out->VSWRYmax = q.value(c++).toDouble();
        out->VSWRYmin = q.value(c++).toDouble();
        out->VSWRXAxisScale = static_cast<AxisScale>(q.value(c++).toInt());
        out->VSWRYAxisScale = static_cast<AxisScale>(q.value(c++).toInt());

        out->CheckImmunityLevel = q.value(c++).toInt();
        out->ImmunityLevelYmax = q.value(c++).toDouble();
        out->ImmunityLevelYmin = q.value(c++).toDouble();
        out->ImmunityLevelXAxisScale = static_cast<AxisScale>(q.value(c++).toInt());
        out->ImmunityLevelYAxisScale = static_cast<AxisScale>(q.value(c++).toInt());
    }

    // 子表
    {
        QSqlQuery q(m_db);
        const QString sql =
            "SELECT id, hardware_template_id, start_freq_hz, stop_freq_hz, step_size, step_mode, dwell_time_ms, "
            "       freq_plan, freq_table_id, immunity_level_type, immunity_level_table_id, immunity_level_value, "
            "       upper_tolerance_db, lower_tolerance_db, "
            "       generator_modulation, generator_plum_period, generator_plum_width, ordinal "
            "FROM TestSubBands WHERE test_template_id=:id "
            "ORDER BY ordinal ASC, id ASC";
        QVariantMap b;
        b[":id"] = id;
        if (!executeQuery(q, sql, b, "Load TestSubBands")) {
            return out;
        }
        QVector<TestSubBandPtr> subs;
        while (q.next()) {
            auto sb = QSharedPointer<TestSubBand>::create();
            int c = 0;
            sb->id = q.value(c++).toInt();
            sb->hardwareTemplateID = q.value(c++).toInt();
            sb->startFreq = q.value(c++).toDouble();
            sb->stopFreq = q.value(c++).toDouble();
            sb->stepSize = q.value(c++).toDouble();
            sb->stepMode = static_cast<AxisScale>(q.value(c++).toInt());
            sb->dwellTime = q.value(c++).toDouble();
            sb->freqPlan = static_cast<FrequencyPlanType>(q.value(c++).toInt());
            sb->freqTableID = q.value(c++).toInt();
            sb->immunityLevelType = static_cast<ImmunityLevelType>(q.value(c++).toInt());
            sb->immunityLevelTableID = q.value(c++).toInt();
            sb->immunityLevelValue = q.value(c++).toDouble();
            sb->upperTolerance = q.value(c++).toDouble();
            sb->lowerTolerance = q.value(c++).toDouble();
            sb->generatorModulation = static_cast<GeneratorModulationType>(q.value(c++).toInt());
            sb->plumPeriod = q.value(c++).toDouble();
            sb->plumWidth = q.value(c++).toDouble();
            /* ordinal = */ (void)q.value(c++).toInt();

            subs.push_back(sb);
        }
        out->subBands = std::move(subs);
    }
    return out;
}

bool DatabaseManager::insertTestTemplate(TestTemplate &testTemplate)
{
    if (testTemplate.id != 0) {
        qWarning() << "insertTestTemplate: id is not 0, use update instead.";
        return false;
    }
    if (!m_db.transaction()) {
        qWarning() << "insertTestTemplate: start transaction failed";
        return false;
    }

    // 插入主表
    {
        QSqlQuery q(m_db);
        const QString sql =
            "INSERT INTO TestTemplates("
            " name, flow_kind, level_mode, power_measurement, immunity_level_unit, impedance, "
            "calibration_table_id, offset_check, offset, "
            " check_generator_output, generator_output_ymax, generator_output_ymin, "
            " generator_output_x_axis_scale, generator_output_y_axis_scale, "
            " check_amplifier_fp, amplifier_fp_ymax, amplifier_fp_ymin, "
            " amplifier_fp_x_axis_scale, amplifier_fp_y_axis_scale, "
            " check_amplifier_rp, amplifier_rp_ymax, amplifier_rp_ymin, "
            " amplifier_rp_x_axis_scale, amplifier_rp_y_axis_scale, "
            " check_vswr, vswr_ymax, vswr_ymin, vswr_x_axis_scale, vswr_y_axis_scale, "
            " check_immunity_level, immunity_level_ymax, immunity_level_ymin, "
            " immunity_level_x_axis_scale, immunity_level_y_axis_scale"
            ") VALUES("
            " :name, :fk, :lm, :pm, :unit, :imp, :cal,:osch,:osval,"
            " :cgo, :goymax, :goymin, :goxs, :goys,"
            " :cafp, :afpymax, :afpymin, :afpxs, :afpys,"
            " :carp, :arpymax, :arpymin, :arpxs, :arpys,"
            " :cvswr, :vswrymax, :vswrymin, :vswrxs, :vswrys, "
            " :cim, :imlymax, :imlymin, :imlxs, :imlys"
            ")";
        QVariantMap b;
        b[":name"] = testTemplate.name;
        b[":fk"] = static_cast<int>(testTemplate.flowKind);
        b[":lm"] = static_cast<int>(testTemplate.levelMode);
        b[":pm"] = static_cast<int>(testTemplate.powerMeasurement);
        b[":unit"] = testTemplate.immunityLevelUnit;
        b[":imp"] = testTemplate.impedance;
        b[":cal"] = testTemplate.calibrationDataID > 0 ? QVariant(testTemplate.calibrationDataID)
                                                       : QVariant(QVariant::Int);
        b[":osch"] = testTemplate.offsetCheck;
        b[":osval"] = testTemplate.offset;
        // UI 配置
        b[":cgo"] = testTemplate.CheckGeneratorOutput;
        b[":goymax"] = testTemplate.GeneratorOutputYmax;
        b[":goymin"] = testTemplate.GeneratorOutputYmin;
        b[":goxs"] = static_cast<int>(testTemplate.GeneratorOutputXAxisScale);
        b[":goys"] = static_cast<int>(testTemplate.GeneratorOutputYAxisScale);

        b[":cafp"] = testTemplate.CheckAmplifierFP;
        b[":afpymax"] = testTemplate.AmplifierFPYmax;
        b[":afpymin"] = testTemplate.AmplifierFPYmin;
        b[":afpxs"] = static_cast<int>(testTemplate.AmplifierFPXAxisScale);
        b[":afpys"] = static_cast<int>(testTemplate.AmplifierFPYAxisScale);

        b[":carp"] = testTemplate.CheckAmplifierRP;
        b[":arpymax"] = testTemplate.AmplifierRPYmax;
        b[":arpymin"] = testTemplate.AmplifierRPYmin;
        b[":arpxs"] = static_cast<int>(testTemplate.AmplifierRPXAxisScale);
        b[":arpys"] = static_cast<int>(testTemplate.AmplifierRPYAxisScale);

        b[":cvswr"] = testTemplate.CheckVSWR;
        b[":vswrymax"] = testTemplate.VSWRYmax;
        b[":vswrymin"] = testTemplate.VSWRYmin;
        b[":vswrxs"] = static_cast<int>(testTemplate.VSWRXAxisScale);
        b[":vswrys"] = static_cast<int>(testTemplate.VSWRYAxisScale);

        b[":cim"] = testTemplate.CheckImmunityLevel;
        b[":imlymax"] = testTemplate.ImmunityLevelYmax;
        b[":imlymin"] = testTemplate.ImmunityLevelYmin;
        b[":imlxs"] = static_cast<int>(testTemplate.ImmunityLevelXAxisScale);
        b[":imlys"] = static_cast<int>(testTemplate.ImmunityLevelYAxisScale);

        if (!executeQuery(q, sql, b, "Insert TestTemplate main")) {
            m_db.rollback();
            return false;
        }
        testTemplate.id = q.lastInsertId().toInt();
        if (testTemplate.id <= 0) {
            qWarning() << "insertTestTemplate: lastInsertId invalid";
            m_db.rollback();
            return false;
        }
    }

    // 插入子区间
    for (int i = 0; i < testTemplate.subBands.size(); ++i) {
        const TestSubBandPtr &sbp = testTemplate.subBands.at(i);
        if (!sbp)
            continue;
        const TestSubBand &sb = *sbp;

        QSqlQuery q(m_db);
        const QString sql =
            "INSERT INTO TestSubBands("
            " test_template_id, hardware_template_id, start_freq_hz, stop_freq_hz, step_size, step_mode, dwell_time_ms, "
            " freq_plan, freq_table_id, immunity_level_type, immunity_level_table_id, immunity_level_value, "
            " upper_tolerance_db, lower_tolerance_db, generator_modulation, generator_plum_period, generator_plum_width, ordinal"
            ") VALUES("
            " :ttid, :hw, :f0, :f1, :step, :stepMode, :dwell,"
            " :plan, :ftid, :ilt, :ilid, :ilv,"
            " :ut, :lt, :mod, :per, :wid, :ord"
            ")";
        QVariantMap b;
        b[":ttid"] = testTemplate.id;
        b[":hw"] = sb.hardwareTemplateID > 0 ? QVariant(sb.hardwareTemplateID)
                                             : QVariant(QVariant::Int); // NULL;
        b[":f0"] = sb.startFreq;
        b[":f1"] = sb.stopFreq;
        b[":step"] = sb.stepSize;
        b[":stepMode"] = static_cast<int>(sb.stepMode);
        b[":dwell"] = sb.dwellTime;
        b[":plan"] = static_cast<int>(sb.freqPlan);
        b[":ftid"] = sb.freqTableID > 0 ? QVariant(sb.freqTableID)
                                        : QVariant(QVariant::Int);
        b[":ilt"] = static_cast<int>(sb.immunityLevelType);
        b[":ilid"] = sb.immunityLevelTableID > 0 ? QVariant(sb.immunityLevelTableID)
                                                 : QVariant(QVariant::Int);
        b[":ilv"] = sb.immunityLevelValue;
        b[":ut"] = sb.upperTolerance;
        b[":lt"] = sb.lowerTolerance;
        b[":mod"] = static_cast<int>(sb.generatorModulation);
        b[":per"] = sb.plumPeriod;
        b[":wid"] = sb.plumWidth;
        b[":ord"] = i;

        if (!executeQuery(q, sql, b, "Insert TestSubBand")) {
            m_db.rollback();
            return false;
        }
        testTemplate.subBands[i]->id = q.lastInsertId().toInt();
    }

    if (!m_db.commit()) {
        qWarning() << "insertTestTemplate: commit failed";
        m_db.rollback();
        return false;
    }
    return true;
}

bool DatabaseManager::deleteTestTemplate(int id)
{
    if (id <= 0)
        return false;
    QSqlQuery q(m_db);
    const QString sql = "DELETE FROM TestTemplates WHERE id=:id";
    QVariantMap b;
    b[":id"] = id;
    const bool ok = executeQuery(q, sql, b, "Delete TestTemplate");
    if (ok) {
        qDebug() << "Deleted TestTemplate id=" << id << " (subbands cascade).";
    }
    return ok;
}

bool DatabaseManager::updateTestTemplate(const TestTemplate &testTemplate)
{
    if (testTemplate.id <= 0) {
        qWarning() << "updateTestTemplate: invalid id";
        return false;
    }
    if (!m_db.transaction()) {
        qWarning() << "updateTestTemplate: start transaction failed";
        return false;
    }

    // 更新主表
    {
        QSqlQuery q(m_db);
        const QString sql =
            "UPDATE TestTemplates SET "
            " name=:name, flow_kind=:fk, level_mode=:lm, power_measurement=:pm, immunity_level_unit=:unit, impedance=:imp, "
            "calibration_table_id=:cal, offset_check=:osch, offset=:osval, "
            " check_generator_output=:cgo, generator_output_ymax=:goymax, generator_output_ymin=:goymin, "
            " generator_output_x_axis_scale=:goxs, generator_output_y_axis_scale=:goys, "
            " check_amplifier_fp=:cafp, amplifier_fp_ymax=:afpymax, amplifier_fp_ymin=:afpymin, "
            " amplifier_fp_x_axis_scale=:afpxs, amplifier_fp_y_axis_scale=:afpys, "
            " check_amplifier_rp=:carp, amplifier_rp_ymax=:arpymax, amplifier_rp_ymin=:arpymin, "
            " amplifier_rp_x_axis_scale=:arpxs, amplifier_rp_y_axis_scale=:arpys, "
            " check_vswr=:cvswr, vswr_ymax=:vswrymax, vswr_ymin=:vswrymin, vswr_x_axis_scale=:vswrxs, vswr_y_axis_scale=:vswrys, "
            " check_immunity_level=:cim, immunity_level_ymax=:imlymax, immunity_level_ymin=:imlymin, "
            " immunity_level_x_axis_scale=:imlxs, immunity_level_y_axis_scale=:imlys "
            "WHERE id=:id";
        QVariantMap b;
        b[":name"] = testTemplate.name;
        b[":fk"] = static_cast<int>(testTemplate.flowKind);
        b[":lm"] = static_cast<int>(testTemplate.levelMode);
        b[":pm"] = static_cast<int>(testTemplate.powerMeasurement);
        b[":unit"] = testTemplate.immunityLevelUnit;
        b[":imp"] = testTemplate.impedance;
        b[":cal"] = testTemplate.calibrationDataID > 0 ? QVariant(testTemplate.calibrationDataID)
                                                       : QVariant(QVariant::Int);
        b[":osch"] = testTemplate.offsetCheck;
        b[":osval"] = testTemplate.offset;

        b[":cgo"] = testTemplate.CheckGeneratorOutput;
        b[":goymax"] = testTemplate.GeneratorOutputYmax;
        b[":goymin"] = testTemplate.GeneratorOutputYmin;
        b[":goxs"] = static_cast<int>(testTemplate.GeneratorOutputXAxisScale);
        b[":goys"] = static_cast<int>(testTemplate.GeneratorOutputYAxisScale);

        b[":cafp"] = testTemplate.CheckAmplifierFP;
        b[":afpymax"] = testTemplate.AmplifierFPYmax;
        b[":afpymin"] = testTemplate.AmplifierFPYmin;
        b[":afpxs"] = static_cast<int>(testTemplate.AmplifierFPXAxisScale);
        b[":afpys"] = static_cast<int>(testTemplate.AmplifierFPYAxisScale);

        b[":carp"] = testTemplate.CheckAmplifierRP;
        b[":arpymax"] = testTemplate.AmplifierRPYmax;
        b[":arpymin"] = testTemplate.AmplifierRPYmin;
        b[":arpxs"] = static_cast<int>(testTemplate.AmplifierRPXAxisScale);
        b[":arpys"] = static_cast<int>(testTemplate.AmplifierRPYAxisScale);

        b[":cvswr"] = testTemplate.CheckVSWR;
        b[":vswrymax"] = testTemplate.VSWRYmax;
        b[":vswrymin"] = testTemplate.VSWRYmin;
        b[":vswrxs"] = static_cast<int>(testTemplate.VSWRXAxisScale);
        b[":vswrys"] = static_cast<int>(testTemplate.VSWRYAxisScale);

        b[":cim"] = testTemplate.CheckImmunityLevel;
        b[":imlymax"] = testTemplate.ImmunityLevelYmax;
        b[":imlymin"] = testTemplate.ImmunityLevelYmin;
        b[":imlxs"] = static_cast<int>(testTemplate.ImmunityLevelXAxisScale);
        b[":imlys"] = static_cast<int>(testTemplate.ImmunityLevelYAxisScale);

        b[":id"] = testTemplate.id;

        if (!executeQuery(q, sql, b, "Update TestTemplate main")) {
            m_db.rollback();
            return false;
        }
    }

    // 清空旧子区间
    {
        QSqlQuery q(m_db);
        if (!executeQuery(q, "DELETE FROM TestSubBands WHERE test_template_id=:id",
                          {{":id", testTemplate.id}}, "Delete old subbands")) {
            m_db.rollback();
            return false;
        }
    }

    // 重新插入子区间
    for (int i = 0; i < testTemplate.subBands.size(); ++i) {
        const TestSubBandPtr &sbp = testTemplate.subBands.at(i);
        if (!sbp)
            continue;
        const TestSubBand &sb = *sbp;

        QSqlQuery q(m_db);
        const QString sql =
            "INSERT INTO TestSubBands("
            " test_template_id, hardware_template_id, start_freq_hz, stop_freq_hz, step_size, step_mode, dwell_time_ms, "
            " freq_plan, freq_table_id, immunity_level_type, immunity_level_table_id, immunity_level_value, "
            " upper_tolerance_db, lower_tolerance_db, generator_modulation, generator_plum_period, generator_plum_width, ordinal"
            ") VALUES("
            " :ttid, :hw, :f0, :f1, :step, :stepMode, :dwell,"
            " :plan, :ftid, :ilt, :ilid, :ilv,"
            " :ut, :lt, :mod, :per, :wid, :ord"
            ")";
        QVariantMap b;
        b[":ttid"] = testTemplate.id;
        b[":hw"] = sb.hardwareTemplateID;
        b[":f0"] = sb.startFreq;
        b[":f1"] = sb.stopFreq;
        b[":step"] = sb.stepSize;
        b[":stepMode"] = static_cast<int>(sb.stepMode);
        b[":dwell"] = sb.dwellTime;
        b[":plan"] = static_cast<int>(sb.freqPlan);
        b[":ftid"] = sb.freqTableID > 0 ? QVariant(sb.freqTableID)
                                        : QVariant(QVariant::Int);
        b[":ilt"] = static_cast<int>(sb.immunityLevelType);
        b[":ilid"] = sb.immunityLevelTableID > 0 ? QVariant(sb.immunityLevelTableID)
                                                 : QVariant(QVariant::Int);
        b[":ilv"] = sb.immunityLevelValue;
        b[":ut"] = sb.upperTolerance;
        b[":lt"] = sb.lowerTolerance;
        b[":mod"] = static_cast<int>(sb.generatorModulation);
        b[":per"] = sb.plumPeriod;
        b[":wid"] = sb.plumWidth;
        b[":ord"] = i;

        if (!executeQuery(q, sql, b, "Re-insert TestSubBand")) {
            m_db.rollback();
            return false;
        }
        // 注意：这里是 const 引用，无法回填 sb.id；如需回填，请改参数为非 const 或在 DataManager 包装层做一次同步加载
    }

    if (!m_db.commit()) {
        qWarning() << "updateTestTemplate: commit failed";
        m_db.rollback();
        return false;
    }
    return true;
}

/**
 * @brief 在数据库层面复制一个完整的测试模板及其所有子区间。
 * @param sourceTemplateId 要复制的源测试模板的ID。
 * @param err 如果发生错误，将填充错误信息。
 * @return 成功则返回一个指向新创建并加载好的TestTemplate对象的智能指针，失败则返回nullptr。
 */
TestTemplatePtr DatabaseManager::duplicateTestTemplate(int sourceTemplateId, QString *err)
{
    if (sourceTemplateId <= 0) {
        if (err)
            *err = "Invalid source test template ID provided.";
        return nullptr;
    }

    if (!m_db.transaction()) {
        if (err)
            *err = "Failed to start database transaction for duplication.";
        qWarning() << "Failed to start transaction for duplicating test template.";
        return nullptr;
    }

    int newTemplateId = -1;
    try {
        //   复制 TestTemplates 主记录
        QSqlQuery query(m_db);
        QString sourceName;
        query.prepare("SELECT name FROM TestTemplates WHERE id = :id");
        query.bindValue(":id", sourceTemplateId);
        if (!query.exec() || !query.next()) {
            throw std::runtime_error("Source test template not found.");
        }
        sourceName = query.value(0).toString();
        QString newName = generateUniqueTemplateName(sourceName, true);

        QString sql =
            "INSERT INTO TestTemplates ("
            "  name, flow_kind, level_mode, power_measurement, immunity_level_unit, impedance, "
            "  calibration_table_id, offset_check, offset, check_generator_output, generator_output_ymax, "
            "  generator_output_ymin, generator_output_x_axis_scale, generator_output_y_axis_scale, "
            "  check_amplifier_fp, amplifier_fp_ymax, amplifier_fp_ymin, amplifier_fp_x_axis_scale, "
            "  amplifier_fp_y_axis_scale, check_amplifier_rp, amplifier_rp_ymax, amplifier_rp_ymin, "
            "  amplifier_rp_x_axis_scale, amplifier_rp_y_axis_scale, check_vswr, vswr_ymax, vswr_ymin, "
            "  vswr_x_axis_scale, vswr_y_axis_scale, check_immunity_level, immunity_level_ymax, "
            "  immunity_level_ymin, immunity_level_x_axis_scale, immunity_level_y_axis_scale"
            ") SELECT "
            "  :new_name, flow_kind, level_mode, power_measurement, immunity_level_unit, impedance, "
            "  calibration_table_id, offset_check, offset, check_generator_output, generator_output_ymax, "
            "  generator_output_ymin, generator_output_x_axis_scale, generator_output_y_axis_scale, "
            "  check_amplifier_fp, amplifier_fp_ymax, amplifier_fp_ymin, amplifier_fp_x_axis_scale, "
            "  amplifier_fp_y_axis_scale, check_amplifier_rp, amplifier_rp_ymax, amplifier_rp_ymin, "
            "  amplifier_rp_x_axis_scale, amplifier_rp_y_axis_scale, check_vswr, vswr_ymax, vswr_ymin, "
            "  vswr_x_axis_scale, vswr_y_axis_scale, check_immunity_level, immunity_level_ymax, "
            "  immunity_level_ymin, immunity_level_x_axis_scale, immunity_level_y_axis_scale "
            "FROM TestTemplates WHERE id = :source_id";

        QVariantMap bindings;
        bindings[":new_name"] = newName;
        bindings[":source_id"] = sourceTemplateId;

        if (!executeQuery(query, sql, bindings, "Duplicate TestTemplate - Step 1: Insert New Main Record")) {
            throw std::runtime_error("Failed to insert new main test template record.");
        }

        newTemplateId = query.lastInsertId().toInt();
        if (newTemplateId <= 0) {
            throw std::runtime_error("Failed to retrieve ID of the newly created test template.");
        }

        sql =
            "INSERT INTO TestSubBands ("
            "  test_template_id, hardware_template_id, start_freq_hz, stop_freq_hz, step_size, step_mode, "
            "  dwell_time_ms, freq_plan, freq_table_id, immunity_level_type, immunity_level_table_id, "
            "  immunity_level_value, upper_tolerance_db, lower_tolerance_db, generator_modulation, generator_plum_period, generator_plum_width, ordinal"
            ") SELECT "
            "  :new_template_id, hardware_template_id, start_freq_hz, stop_freq_hz, step_size, step_mode, "
            "  dwell_time_ms, freq_plan, freq_table_id, immunity_level_type, immunity_level_table_id, "
            "  immunity_level_value, upper_tolerance_db, lower_tolerance_db, generator_modulation, generator_plum_period, generator_plum_width, ordinal "
            "FROM TestSubBands WHERE test_template_id = :source_template_id";

        bindings.clear();
        bindings[":new_template_id"] = newTemplateId;
        bindings[":source_template_id"] = sourceTemplateId;

        if (!executeQuery(query, sql, bindings, "Duplicate TestTemplate - Step 2: Bulk Copy SubBands")) {
            throw std::runtime_error("Failed to bulk copy associated sub-bands.");
        }

    } catch (const std::runtime_error &e) {
        qWarning() << "Transaction failed during duplicateTestTemplate:" << e.what();
        if (err)
            *err = e.what();
        m_db.rollback();
        return nullptr;
    }

    if (!m_db.commit()) {
        qWarning() << "Failed to commit transaction for duplicating test template.";
        if (err)
            *err = "Database commit failed.";
        m_db.rollback();
        return nullptr;
    }

    qDebug() << "Successfully duplicated test template" << sourceTemplateId << "to new template" << newTemplateId;

    return loadFullTestTemplate(newTemplateId);
}

/**
 * @brief  加载一个完整的硬件模板及其拥有的所有私有设备。
 * @param id 要加载的硬件模板的ID。
 * @return 指向填充好所有数据的HardwareTemplate对象的智能指针。如果失败则返回nullptr。
 */
HardwareTemplatePtr DatabaseManager::loadFullHardwareTemplate(int id)
{
    if (id <= 0) {
        return nullptr;
    }

    //  查询HardwareTemplates主表，获取元数据
    HardwareTemplatePtr hwTemplate = QSharedPointer<HardwareTemplate>::create();
    //  查询主表
    {
        QSqlQuery mainQuery(m_db);
        QString sql = "SELECT name, template_type, template_frequency_min, template_frequency_max FROM HardwareTemplates WHERE id = :id";
        QVariantMap bindings;
        bindings[":id"] = id;
        if (executeQuery(mainQuery, sql, bindings, "Load Full HW - Main") && mainQuery.next()) {
            hwTemplate->id = id;
            hwTemplate->name = mainQuery.value("name").toString();
            hwTemplate->type = static_cast<HardwareTemplateType>(mainQuery.value("template_type").toInt());
            hwTemplate->frequencyMin = mainQuery.value("template_frequency_min").toDouble();
            hwTemplate->frequencyMax = mainQuery.value("template_frequency_max").toDouble();
        } else {
            qWarning() << "Hardware template not found in DB with ID:" << id;
            return nullptr;
        }
    }
    // 查询TemplateDevices表，获取所有属于该模板的设备
    {
        QSqlQuery deviceQuery(m_db);
        QString sql = "SELECT * FROM TemplateDevices WHERE hardware_template_id = :hw_id";
        QVariantMap bindings;
        bindings[":hw_id"] = id;

        if (!executeQuery(deviceQuery, sql, bindings, "Load Full HW - Devices")) {
            qWarning() << "Failed to query devices for hardware template ID:" << id << ". Returning template with metadata only.";
            return hwTemplate; // 仍然返回一个部分加载的模板
        }

        // 遍历设备记录，创建对象并填充到HardwareTemplate的插槽中
        while (deviceQuery.next()) {
            // 为每一行创建一个设备对象
            // 注意：loadFullDevice现在需要被重构为一个从QSqlQuery记录创建对象的辅助函数
            DeviceConfigBasePtr device = createDeviceFromQuery(deviceQuery);
            if (!device) {
                continue; // 如果某个设备创建失败，跳过它
            }

            // 获取这个设备的角色
            DeviceRole role = static_cast<DeviceRole>(deviceQuery.value("device_role").toInt());

            // 核心匹配逻辑：根据角色，将设备指针放入正确的插槽
            switch (role) {
            case DeviceRole::SignalGenerator:
                hwTemplate->d_Generator = qSharedPointerDynamicCast<GeneratorConfig>(device);
                break;
            case DeviceRole::Amplifier:
                hwTemplate->d_Amplifier = qSharedPointerDynamicCast<AmplifierConfig>(device);
                break;
            case DeviceRole::PowerMeterForward:
                hwTemplate->d_FwdPowerMeter = qSharedPointerDynamicCast<PowerMeterConfig>(device);
                break;
            case DeviceRole::PowerMeterReverse:
                hwTemplate->d_RevPowerMeter = qSharedPointerDynamicCast<PowerMeterConfig>(device);
                break;
            case DeviceRole::AntennaRadiates:
                hwTemplate->d_RadiatesAntenna = qSharedPointerDynamicCast<AntennaConfig>(device);
                break;
            case DeviceRole::AntennaReceives:
                hwTemplate->d_ReceivesAntenna = qSharedPointerDynamicCast<AntennaConfig>(device);
                break;
            case DeviceRole::CurrentInjectionProbeInput:
                hwTemplate->d_InjectionTransducer = qSharedPointerDynamicCast<CurrentInjectionProbeConfig>(device);
                break;
            case DeviceRole::CurrentInjectionProbeMonitor:
                hwTemplate->d_MonitoringTransducer = qSharedPointerDynamicCast<CurrentInjectionProbeConfig>(device);
                break;
            case DeviceRole::PowerMeterMonitor:
                hwTemplate->d_MonPowerMeter = qSharedPointerDynamicCast<PowerMeterConfig>(device);
                break;
            case DeviceRole::FieldProbe:
                hwTemplate->d_MonFieldProbes = qSharedPointerDynamicCast<FieldProbesConfig>(device);
                break;
            case DeviceRole::SpectrumAnalyzer:
                hwTemplate->d_MonSpectrumAnalyzer = qSharedPointerDynamicCast<SpectrumAnalyzerConfig>(device);
                break;
            case DeviceRole::Receiver:
                hwTemplate->d_MonReceiver = qSharedPointerDynamicCast<ReceiverConfig>(device);
                break;
                // -- Connectors --
            case DeviceRole::Connector_SIG2PA:
                hwTemplate->c_SIG2PA = qSharedPointerDynamicCast<ConnectorConfig>(device);
                break;
            case DeviceRole::Connector_FWD2PM:
                hwTemplate->c_FWD2PM = qSharedPointerDynamicCast<ConnectorConfig>(device);
                break;
            case DeviceRole::Connector_REV2PM:
                hwTemplate->c_REV2PM = qSharedPointerDynamicCast<ConnectorConfig>(device);
                break;
            case DeviceRole::Connector_PA2Transducers:
                hwTemplate->c_PA2Transducers = qSharedPointerDynamicCast<ConnectorConfig>(device);
                break;
            case DeviceRole::Connector_Transducers2PM:
                hwTemplate->c_Transducers2PM = qSharedPointerDynamicCast<ConnectorConfig>(device);
                break;
            default:
                qWarning() << "loadFullHardwareTemplate: Unknown device role encountered:" << static_cast<int>(role);
                break;
            }
        }
    }
    return hwTemplate;
}

int DatabaseManager::getHardwareTemplateType(int id)
{
    if (id <= 0)
        return -1;
    QSqlQuery q(m_db);
    if (!executeQuery(q,
                      "SELECT template_type FROM HardwareTemplates WHERE id=:id",
                      {{":id", id}},
                      "Get HW template type"))
        return -1;
    if (q.next())
        return q.value(0).toInt();
    return -1;
}

/**
 * @brief (私有辅助函数) 从一个QSqlQuery记录中创建一个完整的设备对象。
 *        这是一个工厂函数，负责将数据库行映射到C++对象。
 * @param query 一个已经执行了'SELECT * FROM TemplateDevices'并且'next()'调用成功的QSqlQuery对象。
 * @return 指向新创建的、数据填充好的设备对象的智能指针。
 */
DeviceConfigBasePtr DatabaseManager::createDeviceFromQuery(QSqlQuery &query)
{
    DeviceType type = static_cast<DeviceType>(query.value("device_type").toInt());
    DeviceConfigBasePtr device = nullptr;

    // 根据类型创建正确的对象实例
    switch (type) {
    case DeviceType::SignalGenerator:
        device.reset(new GeneratorConfig());
        break;
    case DeviceType::Amplifier:
        device.reset(new AmplifierConfig());
        break;
    case DeviceType::PowerMeter:
        device.reset(new PowerMeterConfig());
        break;
    case DeviceType::Antenna:
        device.reset(new AntennaConfig());
        break;
    case DeviceType::FieldProbe:
        device.reset(new FieldProbesConfig());
        break;
    case DeviceType::CurrentInjectionProbe:
        device.reset(new CurrentInjectionProbeConfig());
        break;
    case DeviceType::Connector:
        device.reset(new ConnectorConfig());
        break;
    case DeviceType::SwitchUnits:
        device.reset(new ConnectorConfig());
        break;
    case DeviceType::Receiver:
        device.reset(new ReceiverConfig());
        break;
    case DeviceType::SpectrumAnalyzer:
        device.reset(new SpectrumAnalyzerConfig());
        break;
    default:
        return nullptr;
    }

    // 填充通用属性
    device->gAttributes.ID = query.value("id").toInt();
    device->gAttributes.type = type;
    device->gAttributes.Model = query.value("model").toString();
    device->gAttributes.LibraryPath = query.value("library_path").toString();
    device->gAttributes.InterfaceType = static_cast<DeviceInterfaceType>(query.value("interface_type").toInt());
    device->gAttributes.InterfaceAddr = query.value("interface_addr").toString();

    // 填充特有属性 (需要进行类型转换来访问成员)
    switch (type) {
    case DeviceType::SignalGenerator: {
        // 安全地获取派生类裸指针以便写入成员
        auto gen = static_cast<GeneratorConfig *>(device.data());
        gen->LevelMin = query.value("generator_level_min").toDouble();
        gen->LevelMax = query.value("generator_level_max").toDouble();
        gen->Modulation_Frequency = query.value("generator_mod_frequency").toDouble();
        gen->Modulation_Depth = query.value("generator_mod_depth").toDouble();
        gen->Modulation_Deviation = query.value("generator_mod_deviation").toDouble();
        gen->Modulation_PulseWidth = query.value("generator_mod_pulse_width").toDouble();
        break;
    }

    case DeviceType::Amplifier: {
        auto amp = static_cast<AmplifierConfig *>(device.data());
        amp->InputLevelMax = query.value("amplifier_input_level_max").toDouble();
        amp->CouplerType = query.value("amplifier_coupler_type").toInt();
        amp->CouplerValue = query.value("amplifier_coupler_value").toDouble();
        amp->CouplerTableFWDTableID = query.value("amplifier_fwd_table_id").toInt();
        amp->CouplerTableREVTableID = query.value("amplifier_rev_table_id").toInt();
        break;
    }

    case DeviceType::PowerMeter: {
        auto pm = static_cast<PowerMeterConfig *>(device.data());
        pm->DeviceChannel = query.value("power_meter_channel").toString();
        break;
    }

    case DeviceType::Antenna: {
        auto antenna = static_cast<AntennaConfig *>(device.data());
        antenna->HFactorsTableID = query.value("antenna_h_factors_table_id").toInt();
        antenna->VFactorsTableID = query.value("antenna_v_factors_table_id").toInt();
        break;
    }

    case DeviceType::FieldProbe: {
        auto probe = static_cast<FieldProbesConfig *>(device.data());
        probe->CorrectionXYZTableID = query.value("field_probe_correction_xyz_table_id").toInt();
        break;
    }

    case DeviceType::CurrentInjectionProbe: {
        auto probe = static_cast<CurrentInjectionProbeConfig *>(device.data());
        probe->TransducerTableID = query.value("ci_probe_transducer_table_id").toInt();
        break;
    }

    case DeviceType::Connector: {
        auto connector = static_cast<ConnectorConfig *>(device.data());
        connector->ValueType = query.value("connector_value_type").toInt();
        connector->AttValue = query.value("connector_att_value").toDouble();
        connector->switchPath = query.value("connector_switch_path").toInt();
        connector->switchChannel = query.value("connector_switch_channel").toInt();
        connector->AttTableID = query.value("connector_att_table_id").toInt();
        break;
    }
    case DeviceType::SwitchUnits: {
        auto connector = static_cast<ConnectorConfig *>(device.data());
        connector->ValueType = query.value("connector_value_type").toInt();
        connector->AttValue = query.value("connector_att_value").toDouble();
        connector->switchPath = query.value("connector_switch_path").toInt();
        connector->switchChannel = query.value("connector_switch_channel").toInt();
        connector->AttTableID = query.value("connector_att_table_id").toInt();
        break;
    }

    case DeviceType::Receiver: {
        break;
    }
    case DeviceType::SpectrumAnalyzer: {
        break;
    }

    case DeviceType::Undefined:
    default:
        qWarning() << "not find undefined";
        break;
    }

    return device;
}

AttTableList DatabaseManager::loadAttTable(int tableId)
{
    AttTableList out;

    QSqlQuery q(m_db);
    QString sql = "SELECT x_axis_scale, y_axis_scale FROM AttTables_Meta WHERE id=:id";
    QVariantMap b {{":id", tableId}};
    if (executeQuery(q, sql, b, "Load Att Meta") && q.next()) {
        out.xAxisScale = static_cast<AxisScale>(q.value(0).toInt());
        out.yAxisScale = static_cast<AxisScale>(q.value(1).toInt());
    } else {
        qWarning() << "loadAttTable: meta not found, id=" << tableId;
        return out;
    }

    // Points
    {
        QSqlQuery q(m_db);
        QString sql = "SELECT freq, att FROM AttTables_Points WHERE table_id=:id ORDER BY freq ASC";
        QVariantMap b {{":id", tableId}};
        if (executeQuery(q, sql, b, "Load Att Points")) {
            while (q.next()) {
                AttTableConfig p;
                p.Freq = q.value(0).toDouble();
                p.Att = q.value(1).toDouble();
                out.attList.append(p);
            }
        }
    }
    return out;
}

TransducerTableList DatabaseManager::loadTransducerTable(int tableId)
{
    TransducerTableList result;

    QSqlQuery q(m_db);
    QString sql = "SELECT x_axis_scale, y_axis_scale, x_unit, y_unit, source_unit, target_unit "
                  "FROM TransducerTables_Meta WHERE id = :id";
    QVariantMap b;
    b[":id"] = tableId;
    if (executeQuery(q, sql, b, "Load Transducer Meta") && q.next()) {
        result.xAxisScale = static_cast<AxisScale>(q.value(0).toInt());
        result.yAxisScale = static_cast<AxisScale>(q.value(1).toInt());
        result.xUnit = q.value(2).toString();
        result.yUnit = q.value(3).toString();
        result.sourceUnit = q.value(4).toString();
        result.targetUnit = q.value(5).toString();
    } else {
        qWarning() << "meta not found for TransducerTable id =" << tableId;
        return result;
    }

    {
        QSqlQuery q(m_db);
        QString sql = "SELECT freq, factors FROM TransducerTables_Points "
                      "WHERE table_id = :id ORDER BY freq ASC";
        QVariantMap b;
        b[":id"] = tableId;
        if (executeQuery(q, sql, b, "Load Transducer Points")) {
            while (q.next()) {
                FactorsConfig cfg;
                cfg.Freq = q.value(0).toDouble();
                cfg.Factors = q.value(1).toDouble();
                result.factorsList.append(cfg);
            }
        }
    }
    return result;
}

LimitLineList DatabaseManager::loadLimitLineTable(int tableId)
{
    LimitLineList result;

    QSqlQuery q(m_db);
    QString sql = "SELECT x_axis_scale, y_axis_scale, x_unit, y_unit FROM LimitLines_Meta WHERE id = :id";
    QVariantMap b;
    b[":id"] = tableId;
    if (executeQuery(q, sql, b, "Load LimitLine Meta") && q.next()) {
        result.xAxisScale = static_cast<AxisScale>(q.value(0).toInt());
        result.yAxisScale = static_cast<AxisScale>(q.value(1).toInt());
        result.xUnit = q.value(2).toString();
        result.yUnit = q.value(3).toString();
    } else {
        qWarning() << "meta not found for LimitLineTable id =" << tableId;
        return result;
    }

    {
        QSqlQuery q(m_db);
        QString sql = "SELECT freq, limit_val FROM LimitLines_Points "
                      "WHERE table_id = :id ORDER BY freq ASC";
        QVariantMap b;
        b[":id"] = tableId;
        if (executeQuery(q, sql, b, "Load LimitLine Points")) {
            while (q.next()) {
                LimitLineConfig cfg;
                cfg.Freq = q.value(0).toDouble();
                cfg.Limit = q.value(1).toDouble();
                result.limitList.append(cfg);
            }
        }
    }
    return result;
}

QList<FreqTableConfig> DatabaseManager::loadFreqTable(int tableId)
{
    QList<FreqTableConfig> out;

    QSqlQuery q(m_db);
    QString sql = "SELECT freq FROM FreqTables_Points WHERE table_id=:id ORDER BY freq ASC";
    QVariantMap b {{":id", tableId}};
    if (executeQuery(q, sql, b, "Load Freq Points")) {
        while (q.next()) {
            FreqTableConfig p;
            p.Freq = q.value(0).toDouble();
            out.append(p);
        }
    }
    return out;
}

QList<CalTableConfig> DatabaseManager::loadCalibrationTable(int tableId)
{
    QList<CalTableConfig> out;
    if (tableId <= 0)
        return out;

    QSqlQuery q(m_db);
    const QString sql =
        "SELECT freq, amplitude, fwd_power, rev_power, "
        "       immunity_level_unit, immunity_level, limit_immunity_level, "
        "       swr, loss, close_loop, info "
        "FROM CalibrationTables_Points "
        "WHERE table_id = :id "
        "ORDER BY freq ASC";
    QVariantMap b;
    b[":id"] = tableId;

    if (executeQuery(q, sql, b, "Load Calibration Table - Points")) {
        while (q.next()) {
            CalTableConfig c;
            c.Freq = q.value(0).toDouble();
            c.Amplitude = q.value(1).toDouble();
            c.FwdPower = q.value(2).toDouble();
            c.RevPower = q.value(3).toDouble();
            c.ImmunityLevelUnit = q.value(4).toString();
            c.ImmunityLevel = q.value(5).toDouble();
            c.LimitImmunityLevel = q.value(6).toDouble();
            c.swr = q.value(7).toDouble();
            c.Loss = q.value(8).toDouble();
            c.CloseLoop = q.value(9).toInt() != 0;
            c.info = q.value(10).toString();
            out.append(c);
        }
    }
    return out;
}

/**
 * @brief  在一个数据库事务中，原子地插入一个全新的硬件模板及其拥有的所有私有设备。
 * @param hwTemplate 一个在内存中构建好的、包含所有新设备对象的HardwareTemplate引用。
 *                   成功后，hwTemplate自身的ID和其内部所有设备对象的ID都会被数据库生成的新值回填。
 * @return 如果整个事务成功提交，返回true；否则将回滚并返回false。
 */
bool DatabaseManager::insertHardwareTemplate(HardwareTemplate &hwTemplate)
{
    if (hwTemplate.id != 0) {
        qWarning() << " Template already has an ID. Use update instead.";
        return false;
    }

    if (!m_db.transaction()) {
        qWarning() << "Failed to start transaction for inserting full hardware template.";
        return false;
    }

    try {
        //  插入HardwareTemplates主记录，获取新ID
        QSqlQuery query(m_db);
        QString sql = "INSERT INTO HardwareTemplates (name, template_frequency_min, template_frequency_max, template_type) VALUES (:name, :template_frequency_min, :template_frequency_max, :template_type)";

        QVariantMap bindings;
        bindings[":name"] = hwTemplate.name;
        bindings[":template_frequency_min"] = static_cast<double>(hwTemplate.frequencyMin);
        bindings[":template_frequency_max"] = static_cast<double>(hwTemplate.frequencyMax);
        bindings[":template_type"] = static_cast<int>(hwTemplate.type);

        if (!executeQuery(query, sql, bindings, "Insert HW Template Main Record")) {
            throw std::runtime_error("Failed to insert main hardware template record.");
        }

        int newTemplateId = query.lastInsertId().toInt();
        if (newTemplateId <= 0) {
            throw std::runtime_error("Failed to retrieve new hardware template ID.");
        }
        hwTemplate.id = newTemplateId; // 回填ID到对象中

        // 遍历HardwareTemplate中的所有设备指针，将它们逐个插入数据库
        // 对每一个非空的设备指针，调用insertDevice辅助函数。
        if (hwTemplate.d_Generator && !insertDevice(*hwTemplate.d_Generator, newTemplateId, DeviceRole::SignalGenerator))
            throw std::runtime_error("Failed to insert SignalGenerator device.");

        if (hwTemplate.d_Amplifier && !insertDevice(*hwTemplate.d_Amplifier, newTemplateId, DeviceRole::Amplifier))
            throw std::runtime_error("Failed to insert Amplifier device.");

        if (hwTemplate.d_FwdPowerMeter && !insertDevice(*hwTemplate.d_FwdPowerMeter, newTemplateId, DeviceRole::PowerMeterForward))
            throw std::runtime_error("Failed to insert FwdPowerMeter device.");

        if (hwTemplate.d_RevPowerMeter && !insertDevice(*hwTemplate.d_RevPowerMeter, newTemplateId, DeviceRole::PowerMeterReverse))
            throw std::runtime_error("Failed to insert RevPowerMeter device.");

        if (hwTemplate.d_RadiatesAntenna && !insertDevice(*hwTemplate.d_RadiatesAntenna, newTemplateId, DeviceRole::AntennaRadiates))
            throw std::runtime_error("Failed to insert RadiatesAntenna device.");

        if (hwTemplate.d_ReceivesAntenna && !insertDevice(*hwTemplate.d_ReceivesAntenna, newTemplateId, DeviceRole::AntennaReceives))
            throw std::runtime_error("Failed to insert ReceivesAntenna device.");

        if (hwTemplate.d_InjectionTransducer && !insertDevice(*hwTemplate.d_InjectionTransducer, newTemplateId, DeviceRole::CurrentInjectionProbeInput))
            throw std::runtime_error("Failed to insert InjectionTransducer device.");

        if (hwTemplate.d_MonitoringTransducer && !insertDevice(*hwTemplate.d_MonitoringTransducer, newTemplateId, DeviceRole::CurrentInjectionProbeMonitor))
            throw std::runtime_error("Failed to insert MonitoringTransducer device.");

        if (hwTemplate.d_MonPowerMeter && !insertDevice(*hwTemplate.d_MonPowerMeter, newTemplateId, DeviceRole::PowerMeterMonitor))
            throw std::runtime_error("Failed to insert MonPowerMeter device.");

        if (hwTemplate.d_MonFieldProbes && !insertDevice(*hwTemplate.d_MonFieldProbes, newTemplateId, DeviceRole::FieldProbe))
            throw std::runtime_error("Failed to insert MonFieldProbes device.");

        if (hwTemplate.d_MonReceiver && !insertDevice(*hwTemplate.d_MonReceiver, newTemplateId, DeviceRole::Receiver))
            throw std::runtime_error("Failed to insert MonReceiver device.");

        //        if (hwTemplate.d_SpectrumAnalyzer && !insertDevice(*hwTemplate.d_SpectrumAnalyzer, newTemplateId, DeviceRole::SpectrumAnalyzer))
        //            throw std::runtime_error("Failed to insert SpectrumAnalyzer device.");

        if (hwTemplate.c_SIG2PA && !insertDevice(*hwTemplate.c_SIG2PA, newTemplateId, DeviceRole::Connector_SIG2PA))
            throw std::runtime_error("Failed to insert Connector_SIG2PA device.");

        if (hwTemplate.c_FWD2PM && !insertDevice(*hwTemplate.c_FWD2PM, newTemplateId, DeviceRole::Connector_FWD2PM))
            throw std::runtime_error("Failed to insert Connector_FWD2PM device.");

        if (hwTemplate.c_REV2PM && !insertDevice(*hwTemplate.c_REV2PM, newTemplateId, DeviceRole::Connector_REV2PM))
            throw std::runtime_error("Failed to insert Connector_REV2PM device.");

        if (hwTemplate.c_PA2Transducers && !insertDevice(*hwTemplate.c_PA2Transducers, newTemplateId, DeviceRole::Connector_PA2Transducers))
            throw std::runtime_error("Failed to insert Connector_PA2Transducers device.");

        if (hwTemplate.c_Transducers2PM && !insertDevice(*hwTemplate.c_Transducers2PM, newTemplateId, DeviceRole::Connector_Transducers2PM))
            throw std::runtime_error("Failed to insert Connector_Transducers2PM device.");

    } catch (const std::runtime_error &e) {
        qWarning() << "Transaction failed during insertFullHardwareTemplate:" << e.what();
        m_db.rollback(); // 关键：如果任何一步抛出异常，回滚所有已做的操作
        return false;
    }

    // 如果所有操作都成功，提交事务
    if (!m_db.commit()) {
        qWarning() << "Failed to commit transaction for inserting full hardware template.";
        m_db.rollback(); // 以防万一
        return false;
    }

    qDebug() << "Successfully inserted full hardware template with new ID:" << hwTemplate.id;
    return true;
}

/**
 * @brief 从数据库中删除一个硬件模板。
 * @param id 要删除的硬件模板的ID。
 * @return 如果成功删除，返回true。
 */
bool DatabaseManager::deleteHardwareTemplate(int id)
{
    if (id <= 0)
        return false;

    QSqlQuery query(m_db);

    QString sql = "DELETE FROM HardwareTemplates "
                  "WHERE id = :id";
    QVariantMap bindings;
    bindings[":id"] = static_cast<int>(id);
    try {
        if (!executeQuery(query, sql, bindings, "Delete Hardware Template")) {
            throw std::runtime_error("Failed to Delete main hardware template record.");
        }
    } catch (const std::runtime_error &e) {
        qWarning() << "Transaction failed during delete sHardwareTemplate:" << e.what();
        m_db.rollback();
        return false;
    }

    qDebug() << "Successfully deleted hardware template" << id << "and all its private devices (via CASCADE).";
    return true;
}
/**
 * @brief 更新一个硬件模板及其所有私有设备。
 *        这个函数会同步数据库状态，使其与传入的hwTemplate对象完全一致。
 * @param hwTemplate 包含最终状态的HardwareTemplate对象，其ID必须有效。
 * @return 如果成功，返回true。
 */
bool DatabaseManager::updateHardwareTemplate(const HardwareTemplate &hwTemplate)
{
    if (hwTemplate.id <= 0) {
        qWarning() << " Invalid hardware template ID provided.";
        return false;
    }

    if (!m_db.transaction()) {
        qWarning() << "Failed to start transaction for updating hardware template.";
        return false;
    }

    try {
        QSqlQuery query(m_db);

        QString sql = "UPDATE HardwareTemplates "
                      "SET name = :name, "
                      "    template_frequency_min = :template_frequency_min, "
                      "    template_frequency_max = :template_frequency_max, "
                      "    template_type = :template_type "
                      "WHERE id = :id";
        QVariantMap bindings;
        bindings[":name"] = hwTemplate.name;
        bindings[":template_frequency_min"] = static_cast<double>(hwTemplate.frequencyMin);
        bindings[":template_frequency_max"] = static_cast<double>(hwTemplate.frequencyMax);
        bindings[":template_type"] = static_cast<int>(hwTemplate.type);
        bindings[":id"] = static_cast<int>(hwTemplate.id);

        if (!executeQuery(query, sql, bindings, "Insert HW Template Main Record")) {
            throw std::runtime_error("Failed to update main hardware template record.");
        }

        // 同步设备列表
        QSqlQuery deviceQuery(m_db);
        sql = "DELETE FROM TemplateDevices WHERE hardware_template_id = :hw_id";
        QVariantMap bindingsDev;
        bindingsDev[":hw_id"] = hwTemplate.id;
        if (!executeQuery(deviceQuery, sql, bindingsDev, "Clear old devices for HW Template")) {
            throw std::runtime_error("Failed to clear old devices for update.");
        }

        // 重新插入hwTemplate对象中定义的所有设备
        auto insert_device = [&](const DeviceConfigBasePtr &devicePtr, DeviceRole role) {
            if (devicePtr) {
                devicePtr->gAttributes.ID = 0; // 重置ID，强制创建新记录
                if (!this->insertDevice(*devicePtr, hwTemplate.id, role)) {
                    throw std::runtime_error(QString("Failed to re-insert device for role %1.")
                                                 .arg(static_cast<int>(role))
                                                 .toStdString());
                }
            }
        };

        // 为所有非空的设备插槽调用插入逻辑
        insert_device(hwTemplate.d_Generator, DeviceRole::SignalGenerator);
        insert_device(hwTemplate.d_Amplifier, DeviceRole::Amplifier);
        insert_device(hwTemplate.d_RadiatesAntenna, DeviceRole::AntennaRadiates);
        insert_device(hwTemplate.d_ReceivesAntenna, DeviceRole::AntennaReceives);
        insert_device(hwTemplate.d_InjectionTransducer, DeviceRole::CurrentInjectionProbeInput);
        insert_device(hwTemplate.d_MonitoringTransducer, DeviceRole::CurrentInjectionProbeMonitor);
        insert_device(hwTemplate.d_MonFieldProbes, DeviceRole::FieldProbe);
        insert_device(hwTemplate.d_FwdPowerMeter, DeviceRole::PowerMeterForward);
        insert_device(hwTemplate.d_RevPowerMeter, DeviceRole::PowerMeterReverse);
        insert_device(hwTemplate.d_MonPowerMeter, DeviceRole::PowerMeterMonitor);
        insert_device(hwTemplate.d_MonReceiver, DeviceRole::Receiver);
        insert_device(hwTemplate.c_SIG2PA, DeviceRole::Connector_SIG2PA);
        insert_device(hwTemplate.c_FWD2PM, DeviceRole::Connector_FWD2PM);
        insert_device(hwTemplate.c_REV2PM, DeviceRole::Connector_REV2PM);
        insert_device(hwTemplate.c_PA2Transducers, DeviceRole::Connector_PA2Transducers);
        insert_device(hwTemplate.c_Transducers2PM, DeviceRole::Connector_Transducers2PM);

    } catch (const std::runtime_error &e) {
        qWarning() << "Transaction failed during updateHardwareTemplate:" << e.what();
        m_db.rollback();
        return false;
    }

    return m_db.commit();
}

/**
 * @brief 在数据库层面复制一个完整的硬件模板及其所有私有设备。
 * @param sourceTemplateId 要复制的源模板的ID。
 * @param err 如果发生错误，将填充错误信息。
 * @return 成功则返回一个指向新创建并加载好的HardwareTemplate对象的智能指针，失败则返回nullptr。
 */
HardwareTemplatePtr DatabaseManager::duplicateHardwareTemplate(int sourceTemplateId, QString *err)
{
    if (sourceTemplateId <= 0) {
        if (err)
            *err = "Invalid source template ID provided.";
        return nullptr;
    }

    if (!m_db.transaction()) {
        if (err)
            *err = "Failed to start database transaction for duplication.";
        qWarning() << "Failed to start transaction for duplicating hardware template.";
        return nullptr;
    }

    int newTemplateId = -1;
    try {
        //复制 HardwareTemplates 主记录
        QSqlQuery query(m_db);

        QString sql = "SELECT name, template_frequency_min, template_frequency_max, template_type FROM HardwareTemplates WHERE id = :id";
        if (!executeQuery(query, sql, {{":id", sourceTemplateId}}, "Duplicate HW - Step 1a: Select Source") || !query.next()) {
            throw std::runtime_error("Source hardware template not found.");
        }
        QString sourceName = query.value("name").toString();
        QVariant freqMin = query.value("template_frequency_min");
        QVariant freqMax = query.value("template_frequency_max");
        int templateType = query.value("template_type").toInt();

        QString newName = generateUniqueTemplateName(sourceName, false);
        sql = "INSERT INTO HardwareTemplates (name, template_frequency_min, template_frequency_max, template_type) VALUES (:name, :min, :max, :type)";
        QVariantMap bindings;
        bindings[":name"] = newName;
        bindings[":min"] = freqMin;
        bindings[":max"] = freqMax;
        bindings[":type"] = templateType;

        if (!executeQuery(query, sql, bindings, "Duplicate HW - Step 1b: Insert New Main Record")) {
            throw std::runtime_error("Failed to insert new main hardware template record.");
        }

        newTemplateId = query.lastInsertId().toInt();
        if (newTemplateId <= 0) {
            throw std::runtime_error("Failed to retrieve ID of the newly created template.");
        }

        sql =
            "INSERT INTO TemplateDevices ("
            // 目标列列表 (注意：第一个是新的template_id)
            "  hardware_template_id, device_role, device_type, model, library_path, "
            "  interface_type, interface_addr, generator_level_min, generator_level_max, "
            "  generator_mod_frequency, generator_mod_depth, generator_mod_deviation, "
            "  generator_mod_pulse_width, amplifier_input_level_max, amplifier_coupler_type, "
            "  amplifier_coupler_value, amplifier_fwd_table_id, amplifier_rev_table_id, "
            "  power_meter_channel, antenna_h_factors_table_id, antenna_v_factors_table_id, "
            "  field_probe_correction_xyz_table_id, ci_probe_transducer_table_id, "
            "  connector_value_type, connector_att_value, connector_switch_path, "
            "  connector_switch_channel, connector_att_table_id"
            ") "
            "SELECT "
            // 源列列表 (注意：第一个是新template_id的占位符)
            "  :new_template_id, device_role, device_type, model, library_path, "
            "  interface_type, interface_addr, generator_level_min, generator_level_max, "
            "  generator_mod_frequency, generator_mod_depth, generator_mod_deviation, "
            "  generator_mod_pulse_width, amplifier_input_level_max, amplifier_coupler_type, "
            "  amplifier_coupler_value, amplifier_fwd_table_id, amplifier_rev_table_id, "
            "  power_meter_channel, antenna_h_factors_table_id, antenna_v_factors_table_id, "
            "  field_probe_correction_xyz_table_id, ci_probe_transducer_table_id, "
            "  connector_value_type, connector_att_value, connector_switch_path, "
            "  connector_switch_channel, connector_att_table_id "
            "FROM TemplateDevices WHERE hardware_template_id = :source_template_id";

        bindings.clear();
        bindings[":new_template_id"] = newTemplateId;
        bindings[":source_template_id"] = sourceTemplateId;

        if (!executeQuery(query, sql, bindings, "Duplicate HW - Step 2: Bulk Copy Devices")) {
            throw std::runtime_error("Failed to bulk copy associated devices.");
        }

    } catch (const std::runtime_error &e) {
        qWarning() << "Transaction failed during duplicateHardwareTemplate:" << e.what();
        if (err)
            *err = e.what();
        m_db.rollback();
        return nullptr;
    }

    //提交事务并加载返回新模板
    if (!m_db.commit()) {
        qWarning() << "Failed to commit transaction for duplicating hardware template.";
        if (err)
            *err = "Database commit failed.";
        m_db.rollback(); // 尝试回滚
        return nullptr;
    }

    qDebug() << "Successfully duplicated hardware template" << sourceTemplateId << "to new template" << newTemplateId;

    // 复用现有的加载函数来获取完整的 C++ 对象
    return loadFullHardwareTemplate(newTemplateId);
}

/**
 * @brief 根据一个基础名称，生成一个在数据库中唯一的硬件模板名称。
 *        例如，如果 "MyTemplate" 已存在，它会尝试 "MyTemplate - Copy", "MyTemplate - Copy 2" 等。
 * @param baseName 原始名称。
 * @return 一个保证唯一的名称。
 */

QString DatabaseManager::generateUniqueTemplateName(const QString &baseName, bool isTestTemplate)
{
    QSqlQuery query(m_db);
    QString tableName = (isTestTemplate) ? "TestTemplates" : "HardwareTemplates";
    QString sql = "SELECT name FROM " + tableName;

    QSet<QString> existingNames;
    if (executeQuery(query, sql, {}, "Generate Unique Name - Fetching existing")) {
        while (query.next()) {
            existingNames.insert(query.value(0).toString());
        }
    }

    // 检查原始名称是否可用 (去掉可能存在的 " - Copy X" 后缀)
    QString cleanBaseName = baseName;
    QRegExp copyPattern(" - Copy( \\d+)?$");
    cleanBaseName.remove(copyPattern);

    QString newName = cleanBaseName + " - Copy";
    if (!existingNames.contains(newName)) {
        return newName;
    }

    int i = 2;
    while (true) {
        newName = QString("%1 - Copy %2").arg(cleanBaseName).arg(i++);
        if (!existingNames.contains(newName)) {
            return newName;
        }
    }
    return QString();
}

/**
 * @brief  向TemplateDevices表中插入一条完整的私有设备记录。
 * @param device 要插入的设备对象，其ID将被数据库生成的新值回填。
 * @param hardwareTemplateId 该设备所属的硬件模板的ID。
 * @param role 该设备在模板中扮演的角色。
 * @return 如果成功，返回true。
 */
bool DatabaseManager::insertDevice(DeviceConfigBase &device, int hardwareTemplateId, DeviceRole role)
{
    // 动态构建SQL语句和值列表
    QStringList columns = {
        "hardware_template_id", "device_role", "device_type",
        "model", "library_path",
        "interface_type",
        "interface_addr"};
    QVariantList values = {
        hardwareTemplateId,
        static_cast<int>(role),
        static_cast<int>(device.gAttributes.type),
        device.gAttributes.Model,
        device.gAttributes.LibraryPath,
        static_cast<int>(device.gAttributes.InterfaceType),
        device.gAttributes.InterfaceAddr};

    // 根据设备类型，添加特有属性的列和值
    switch (device.gAttributes.type) {
    case DeviceType::SignalGenerator: {
        const auto &gen = static_cast<const GeneratorConfig &>(device);
        columns << "generator_level_min"
                << "generator_level_max"
                << "generator_mod_frequency"
                << "generator_mod_depth"
                << "generator_mod_deviation"
                << "generator_mod_pulse_width";
        values << gen.LevelMin << gen.LevelMax << gen.Modulation_Frequency << gen.Modulation_Depth << gen.Modulation_Deviation << gen.Modulation_PulseWidth;
        break;
    }
    case DeviceType::Amplifier: {
        const auto &amp = static_cast<const AmplifierConfig &>(device);
        columns << "amplifier_input_level_max"
                << "amplifier_coupler_type"
                << "amplifier_coupler_value"
                << "amplifier_fwd_table_id"
                << "amplifier_rev_table_id";

        values << amp.InputLevelMax << amp.CouplerType << amp.CouplerValue
               << (amp.CouplerTableFWDTableID > 0 ? QVariant(amp.CouplerTableFWDTableID) : QVariant())
               << (amp.CouplerTableREVTableID > 0 ? QVariant(amp.CouplerTableREVTableID) : QVariant());
        break;
    }
    case DeviceType::PowerMeter: {
        const auto &pm = static_cast<const PowerMeterConfig &>(device);
        columns << "power_meter_channel";
        values << pm.DeviceChannel;
        break;
    }
    case DeviceType::Antenna: {
        const auto &antenna = static_cast<const AntennaConfig &>(device);
        columns << "antenna_h_factors_table_id"
                << "antenna_v_factors_table_id";
        values << (antenna.HFactorsTableID > 0 ? QVariant(antenna.HFactorsTableID) : QVariant())
               << (antenna.VFactorsTableID > 0 ? QVariant(antenna.VFactorsTableID) : QVariant());
        break;
    }
    case DeviceType::FieldProbe: {
        const auto &probe = static_cast<const FieldProbesConfig &>(device);
        columns << "field_probe_correction_xyz_table_id";
        values << (probe.CorrectionXYZTableID > 0 ? QVariant(probe.CorrectionXYZTableID) : QVariant());
        break;
    }
    case DeviceType::CurrentInjectionProbe: {
        const auto &probe = static_cast<const CurrentInjectionProbeConfig &>(device);
        columns << "ci_probe_transducer_table_id";
        values << (probe.TransducerTableID > 0 ? QVariant(probe.TransducerTableID) : QVariant());
        break;
    }
    case DeviceType::Connector: {
        const auto &connector = static_cast<const ConnectorConfig &>(device);
        columns << "connector_value_type"
                << "connector_att_value"
                << "connector_switch_path"
                << "connector_switch_channel"
                << "connector_att_table_id";
        values << connector.ValueType << connector.AttValue << connector.switchPath << connector.switchChannel
               << (connector.AttTableID > 0 ? QVariant(connector.AttTableID) : QVariant());
        break;
    }
    case DeviceType::Receiver: {
        break;
    }
    case DeviceType::SpectrumAnalyzer: {
        // 没有特有属性，不需要添加任何列和值
        break;
    }
    case DeviceType::SwitchUnits: {
        const auto &connector = static_cast<const ConnectorConfig &>(device);
        columns << "connector_value_type"
                << "connector_att_value"
                << "connector_switch_path"
                << "connector_switch_channel"
                << "connector_att_table_id";
        values << connector.ValueType << connector.AttValue << connector.switchPath << connector.switchChannel
               << (connector.AttTableID > 0 ? QVariant(connector.AttTableID) : QVariant());
        break;
    }
    default:
        qWarning() << "insertDevice: Attempted to insert device with Undefined or unknown type.";
        return false;
    }

    //   构建列名部分
    QString column_str = columns.join(", ");

    // 构建占位符部分
    QString placeholder_str;
    for (int i = 0; i < columns.size(); ++i) {
        if (i > 0) {
            placeholder_str += ", ";
        }
        placeholder_str += "?";
    }

    // 组合成最终的SQL语句
    QString final_sql = QString("INSERT INTO TemplateDevices (%1) VALUES (%2)")
                            .arg(column_str)
                            .arg(placeholder_str);

    QSqlQuery query(m_db);
    if (!query.prepare(final_sql)) {
        qWarning() << "FATAL: SQL prepare failed for insertDevice. This is a programming error.";
        qWarning() << "Generated SQL:" << final_sql;
        qWarning() << "Error:" << query.lastError().text();
        return false;
    }

    // 绑定所有值
    for (const QVariant &value : values) {
        query.addBindValue(value);
    }
    if (!query.exec()) {
        qWarning() << "Query exec failed: Insert TemplateDevice" << query.lastError().text();
        qWarning() << "Failing query:" << query.lastQuery();
        qWarning() << "Bound values:" << query.boundValues();
        return false;
    }

    device.gAttributes.ID = query.lastInsertId().toInt();
    return true;
}

int DatabaseManager::insertNewParameterTableMeta(const QString &name, const ParamTableKind type)
{
    QString tableName;
    QString sql;
    QVariantMap b;

    if (type == ParamTableKind::Attenuation) {
        tableName = "AttTables_Meta";
        sql = QString("INSERT INTO %1 (name, x_axis_scale, y_axis_scale) "
                      "VALUES (:name, :x, :y)")
                  .arg(tableName);
        b[":name"] = name;
        b[":x"] = static_cast<int>(AxisScale::Linear);
        b[":y"] = static_cast<int>(AxisScale::Logarithmic);
    } else if (type == ParamTableKind::Transducer) {
        tableName = "TransducerTables_Meta";
        sql = QString("INSERT INTO %1 (name, x_axis_scale, y_axis_scale, x_unit, y_unit, source_unit, target_unit) "
                      "VALUES (:name, :x, :y, :xu, :yu, :su, :tu)")
                  .arg(tableName);
        b[":name"] = name;
        b[":x"] = static_cast<int>(AxisScale::Linear);
        b[":y"] = static_cast<int>(AxisScale::Linear);
        b[":xu"] = STR_UNIT_MHZ;
        b[":yu"] = STR_UNIT_DBM;
        b[":su"] = STR_UNIT_DBM;
        b[":tu"] = STR_UNIT_VM;

    } else if (type == ParamTableKind::LimitLine) {
        tableName = "LimitLines_Meta";
        sql = QString("INSERT INTO %1 (name, x_axis_scale, y_axis_scale, x_unit, y_unit) "
                      "VALUES (:name, :x, :y, :xu, :yu)")
                  .arg(tableName);
        b[":name"] = name;
        b[":x"] = static_cast<int>(AxisScale::Linear);
        b[":y"] = static_cast<int>(AxisScale::Linear);
        b[":xu"] = STR_UNIT_MHZ;
        b[":yu"] = STR_UNIT_VM;
    } else if (type == ParamTableKind::Frequency) {
        tableName = "FreqTables_Meta";
        sql = QString("INSERT INTO %1 (name) VALUES (:name)").arg(tableName);
        b[":name"] = name;
    } else if (type == ParamTableKind::Cal) {
        tableName = "CalibrationTables_Meta";
        sql = QString("INSERT INTO %1 (name) VALUES (:name)").arg(tableName);
        b[":name"] = name;
    } else {
        qWarning() << "insertNewParameterTableMeta: Unsupported type:" << (int)type;
        return -1;
    }

    QSqlQuery q(m_db);
    if (!executeQuery(q, sql, b, "Insert parameter table meta"))
        return -1;
    return q.lastInsertId().toInt();
}

bool DatabaseManager::deleteParameterTable(int id, const ParamTableKind type)
{
    if (id <= 0)
        return false;

    QString metaTable;
    if (type == ParamTableKind::Attenuation)
        metaTable = "AttTables_Meta";
    else if (type == ParamTableKind::Transducer)
        metaTable = "TransducerTables_Meta";
    else if (type == ParamTableKind::LimitLine)
        metaTable = "LimitLines_Meta";
    else if (type == ParamTableKind::Frequency)
        metaTable = "FreqTables_Meta";
    else if (type == ParamTableKind::Cal)
        metaTable = "CalibrationTables_Meta";
    else {
        qWarning() << "deleteParameterTable: unsupported type:" << (int)type;
        return false;
    }

    QSqlQuery q(m_db);
    const QString sql = QString("DELETE FROM %1 WHERE id = :id").arg(metaTable);
    QVariantMap b {{":id", id}};
    return executeQuery(q, sql, b, "Delete Parameter Table");
}

bool DatabaseManager::saveAttTable(int tableId, const QString &name, const AttTableList &t)
{
    if (!m_db.transaction())
        return false;

    QSqlQuery q(m_db);
    if (!executeQuery(q,
                      "UPDATE AttTables_Meta SET name=:name, x_axis_scale=:x, y_axis_scale=:y WHERE id=:id",
                      {{":name", name}, {":x", static_cast<int>(t.xAxisScale)}, {":y", static_cast<int>(t.yAxisScale)}, {":id", tableId}},
                      "Update Att Meta")) {
        m_db.rollback();
        return false;
    }

    if (!executeQuery(q,
                      "DELETE FROM AttTables_Points WHERE table_id=:id",
                      {{":id", tableId}},
                      "Delete Att Points")) {
        m_db.rollback();
        return false;
    }

    //  批量插入 Points（命名占位 + execBatch）
    if (!t.attList.isEmpty()) {
        QSqlQuery ins(m_db);
        if (!ins.prepare("INSERT INTO AttTables_Points (table_id, freq, att) "
                         "VALUES (:id, :freq, :att)")) {
            qWarning() << "Prepare failed (Att points):" << ins.lastError().text();
            m_db.rollback();
            return false;
        }
        QVariantList ids, freqs, atts;
        ids.reserve(t.attList.size());
        freqs.reserve(t.attList.size());
        atts.reserve(t.attList.size());
        for (const auto &p : t.attList) {
            ids << tableId;
            freqs << p.Freq;
            atts << p.Att;
        }
        ins.bindValue(":id", ids);
        ins.bindValue(":freq", freqs);
        ins.bindValue(":att", atts);
        if (!ins.execBatch()) {
            qWarning() << "execBatch failed (Att points):" << ins.lastError().text();
            m_db.rollback();
            return false;
        }
    }
    return m_db.commit();
}

bool DatabaseManager::saveTransducerTable(int tableId, const QString &name, const TransducerTableList &t)
{
    if (!m_db.transaction())
        return false;

    QSqlQuery q(m_db);
    //更新 Meta
    if (!executeQuery(q,
                      "UPDATE TransducerTables_Meta "
                      "SET name=:name, x_axis_scale=:x, y_axis_scale=:y, x_unit=:xu, y_unit=:yu, source_unit=:su, target_unit=:tu "
                      "WHERE id=:id",
                      {{":name", name},
                       {":x", static_cast<int>(t.xAxisScale)},
                       {":y", static_cast<int>(t.yAxisScale)},
                       {":xu", t.xUnit},
                       {":yu", t.yUnit},
                       {":su", t.sourceUnit},
                       {":tu", t.targetUnit},
                       {":id", tableId}},
                      "Update Transducer Meta")) {
        m_db.rollback();
        return false;
    }

    //清旧 Points
    if (!executeQuery(q,
                      "DELETE FROM TransducerTables_Points WHERE table_id=:id",
                      {{":id", tableId}},
                      "Delete Transducer Points")) {
        m_db.rollback();
        return false;
    }

    //批量插入 Points
    if (!t.factorsList.isEmpty()) {
        QSqlQuery ins(m_db);
        if (!ins.prepare("INSERT INTO TransducerTables_Points (table_id, freq, factors) "
                         "VALUES (:id, :freq, :factors)")) {
            qWarning() << "Prepare failed (Transducer points):" << ins.lastError().text();
            m_db.rollback();
            return false;
        }
        QVariantList ids, freqs, factors;
        ids.reserve(t.factorsList.size());
        freqs.reserve(t.factorsList.size());
        factors.reserve(t.factorsList.size());
        for (const auto &p : t.factorsList) {
            ids << tableId;
            freqs << p.Freq;
            factors << p.Factors;
        }
        ins.bindValue(":id", ids);
        ins.bindValue(":freq", freqs);
        ins.bindValue(":factors", factors);
        if (!ins.execBatch()) {
            qWarning() << "execBatch failed (Transducer points):" << ins.lastError().text();
            m_db.rollback();
            return false;
        }
    }
    return m_db.commit();
}

bool DatabaseManager::saveLimitLineTable(int tableId, const QString &name, const LimitLineList &t)
{
    if (!m_db.transaction())
        return false;

    QSqlQuery q(m_db);
    //更新 Meta
    if (!executeQuery(q,
                      "UPDATE LimitLines_Meta SET name=:name, x_axis_scale=:x, y_axis_scale=:y, x_unit=:xu, y_unit=:yu WHERE id=:id",
                      {{":name", name}, {":x", static_cast<int>(t.xAxisScale)}, {":y", static_cast<int>(t.yAxisScale)}, {":xu", t.xUnit}, {":yu", t.yUnit}, {":id", tableId}},
                      "Update LimitLine Meta")) {
        m_db.rollback();
        return false;
    }

    //清旧 Points
    if (!executeQuery(q,
                      "DELETE FROM LimitLines_Points WHERE table_id=:id",
                      {{":id", tableId}},
                      "Delete LimitLine Points")) {
        m_db.rollback();
        return false;
    }

    //批量插入 Points
    if (!t.limitList.isEmpty()) {
        QSqlQuery ins(m_db);
        if (!ins.prepare("INSERT INTO LimitLines_Points (table_id, freq, limit_val) "
                         "VALUES (:id, :freq, :limit)")) {
            qWarning() << "Prepare failed (Limit points):" << ins.lastError().text();
            m_db.rollback();
            return false;
        }
        QVariantList ids, freqs, limits;
        ids.reserve(t.limitList.size());
        freqs.reserve(t.limitList.size());
        limits.reserve(t.limitList.size());
        for (const auto &p : t.limitList) {
            ids << tableId;
            freqs << p.Freq;
            limits << p.Limit;
        }
        ins.bindValue(":id", ids);
        ins.bindValue(":freq", freqs);
        ins.bindValue(":limit", limits);
        if (!ins.execBatch()) {
            qWarning() << "execBatch failed (Limit points):" << ins.lastError().text();
            m_db.rollback();
            return false;
        }
    }
    return m_db.commit();
}

bool DatabaseManager::saveFreqTable(int tableId, const QString &name, const QList<FreqTableConfig> &rows)
{
    if (!m_db.transaction())
        return false;

    QSqlQuery q(m_db);
    if (!executeQuery(q, "UPDATE FreqTables_Meta SET name=:name WHERE id=:id",
                      {{":name", name}, {":id", tableId}}, "Update Freq Meta")) {
        m_db.rollback();
        return false;
    }
    if (!executeQuery(q,
                      "DELETE FROM FreqTables_Points WHERE table_id=:id",
                      {{":id", tableId}}, "Delete Freq Points")) {
        m_db.rollback();
        return false;
    }

    // 批量插入
    if (!rows.isEmpty()) {
        QSqlQuery ins(m_db);
        if (!ins.prepare("INSERT INTO FreqTables_Points (table_id, freq) "
                         "VALUES (:id, :freq)")) {
            qWarning() << "Prepare failed (Freq points):" << ins.lastError().text();
            m_db.rollback();
            return false;
        }
        QVariantList ids, freqs;
        ids.reserve(rows.size());
        freqs.reserve(rows.size());
        for (const auto &p : rows) {
            ids << tableId;
            freqs << p.Freq;
        }
        ins.bindValue(":id", ids);
        ins.bindValue(":freq", freqs);
        if (!ins.execBatch()) {
            qWarning() << "execBatch failed (Freq points):" << ins.lastError().text();
            m_db.rollback();
            return false;
        }
    }
    return m_db.commit();
}

bool DatabaseManager::saveCalibrationTable(int tableId, const QString &name, const QList<CalTableConfig> &rows)
{
    if (!m_db.transaction())
        return false;

    QSqlQuery q(m_db);
    if (!executeQuery(q,
                      "UPDATE CalibrationTables_Meta SET name=:name, updated_at=CURRENT_TIMESTAMP WHERE id=:id",
                      {{":name", name}, {":id", tableId}}, "Update Cal Meta")) {
        m_db.rollback();
        return false;
    }

    //清旧 Points
    if (!executeQuery(q,
                      "DELETE FROM CalibrationTables_Points WHERE table_id=:id",
                      {{":id", tableId}},
                      "Delete Calibration Points")) {
        m_db.rollback();
        return false;
    }

    //批量插入 Points（命名占位+execBatch）
    if (!rows.isEmpty()) {
        QSqlQuery ins(m_db);
        if (!ins.prepare("INSERT INTO CalibrationTables_Points ("
                         "table_id, freq, amplitude, fwd_power, rev_power, "
                         "immunity_level_unit, immunity_level, limit_immunity_level, "
                         "swr, loss, close_loop, info) "
                         "VALUES (:id, :freq, :amp, :fwd, :rev, "
                         ":unit, :level, :limit, :swr, :loss, :loop, :info)")) {
            qWarning() << "Prepare failed (Cal points):" << ins.lastError().text();
            m_db.rollback();
            return false;
        }

        QVariantList idL, freqL, ampL, fwdL, revL, unitL, levelL, limitL, swrL, lossL, loopL, infoL;
        idL.reserve(rows.size());
        for (const auto &c : rows) {
            idL << tableId;
            freqL << c.Freq;
            ampL << c.Amplitude;
            fwdL << c.FwdPower;
            revL << c.RevPower;
            unitL << c.ImmunityLevelUnit;
            levelL << c.ImmunityLevel;
            limitL << c.LimitImmunityLevel;
            swrL << c.swr;
            lossL << c.Loss;
            loopL << (c.CloseLoop ? 1 : 0);
            infoL << c.info;
        }
        ins.bindValue(":id", idL);
        ins.bindValue(":freq", freqL);
        ins.bindValue(":amp", ampL);
        ins.bindValue(":fwd", fwdL);
        ins.bindValue(":rev", revL);
        ins.bindValue(":unit", unitL);
        ins.bindValue(":level", levelL);
        ins.bindValue(":limit", limitL);
        ins.bindValue(":swr", swrL);
        ins.bindValue(":loss", lossL);

        ins.bindValue(":loop", loopL);
        ins.bindValue(":info", infoL);

        if (!ins.execBatch()) {
            qWarning() << "execBatch failed (Cal points):" << ins.lastError().text();
            m_db.rollback();
            return false;
        }
    }

    //可选：如有 updated_at 字段，可顺便“触碰”Meta
    if (!executeQuery(q,
                      "UPDATE CalibrationTables_Meta SET updated_at=CURRENT_TIMESTAMP WHERE id=:id",
                      {{":id", tableId}}, "Touch Cal Meta")) {
        m_db.rollback();
        return false;
    }

    return m_db.commit();
}

/**
 * @brief 复制一个参数表，包括其元数据和所有数据点。
 * @param sourceTableId 要复制的源表的ID。
 * @param kind 源表的类型 (Attenuation, Transducer, etc.)。
 * @param newName 为新表指定的名称。
 * @param err 错误信息输出。
 * @return 成功则返回新创建的表的ID，失败返回-1。
 */
int DatabaseManager::duplicateParameterTable(int sourceTableId, ParamTableKind kind, const QString &newName, QString *err)
{
    if (sourceTableId <= 0 || newName.isEmpty()) {
        if (err)
            *err = "Invalid source ID or new name provided.";
        return -1;
    }

    if (!m_db.transaction()) {
        if (err)
            *err = "Failed to start database transaction for table duplication.";
        qWarning() << "Failed to start transaction for duplicating parameter table.";
        return -1;
    }

    int newTableId = -1;
    try {
        QString metaTable;
        QString pointsTable;
        QString metaColumns;   // 除 id 和 name 之外的列
        QString pointsColumns; // 除 id 和 table_id 之外的列

        switch (kind) {
        case ParamTableKind::Attenuation:
            metaTable = "AttTables_Meta";
            pointsTable = "AttTables_Points";
            metaColumns = "x_axis_scale, y_axis_scale";
            pointsColumns = "freq, att";
            break;
        case ParamTableKind::Transducer:
            metaTable = "TransducerTables_Meta";
            pointsTable = "TransducerTables_Points";
            metaColumns = "x_axis_scale, y_axis_scale, x_unit, y_unit, source_unit, target_unit";
            pointsColumns = "freq, factors";
            break;
        case ParamTableKind::LimitLine:
            metaTable = "LimitLines_Meta";
            pointsTable = "LimitLines_Points";
            metaColumns = "x_axis_scale, y_axis_scale, x_unit, y_unit";
            pointsColumns = "freq, limit_val";
            break;
        case ParamTableKind::Frequency:
            metaTable = "FreqTables_Meta";
            pointsTable = "FreqTables_Points";
            metaColumns = ""; // 没有其他元数据列
            pointsColumns = "freq";
            break;
        default:
            throw std::runtime_error("Unsupported table kind for duplication.");
        }

        QSqlQuery query(m_db);

        QString sql = QString("INSERT INTO %1 (name, %2) SELECT :new_name, %2 FROM %1 WHERE id = :source_id")
                          .arg(metaTable)
                          .arg(metaColumns);
        if (metaColumns.isEmpty()) {
            sql = QString("INSERT INTO %1 (name) VALUES (:new_name)").arg(metaTable);
        }

        QVariantMap bindings;
        bindings[":new_name"] = newName;
        bindings[":source_id"] = sourceTableId;
        if (!executeQuery(query, sql, bindings, "Duplicate Parameter Table - Step 1: Copy Meta")) {
            throw std::runtime_error("Failed to copy meta record.");
        }

        newTableId = query.lastInsertId().toInt();
        if (newTableId <= 0) {
            throw std::runtime_error("Failed to retrieve new table ID.");
        }

        //  复制数据点记录
        sql = QString("INSERT INTO %1 (table_id, %2) SELECT :new_table_id, %2 FROM %1 WHERE table_id = :source_table_id")
                  .arg(pointsTable)
                  .arg(pointsColumns);

        bindings.clear();
        bindings[":new_table_id"] = newTableId;
        bindings[":source_table_id"] = sourceTableId;

        if (!executeQuery(query, sql, bindings, "Duplicate Parameter Table - Step 2: Copy Points")) {
            throw std::runtime_error("Failed to copy points data.");
        }

    } catch (const std::runtime_error &e) {
        qWarning() << "Transaction failed during duplicateParameterTable:" << e.what();
        if (err)
            *err = e.what();
        m_db.rollback();
        return -1;
    }

    if (!m_db.commit()) {
        qWarning() << "Failed to commit transaction for duplicating parameter table.";
        if (err)
            *err = "Database commit failed.";
        m_db.rollback();
        return -1;
    }

    qDebug() << "Successfully duplicated parameter table" << sourceTableId << "to new table" << newTableId;
    return newTableId;
}
